'How to get back a value from a customly created widget in Flutter

I am showing a showModalBottomSheet using a function. I want that as soon as it closes, value of a variable should change. I wanted to change value of two variables, but I am not able to change for even one. Please help me with this. I tried to make my own onChanged and also tried to return the value using function, but nothing happens.

This is the function, please scroll to the last of it and check out the onTap function and return.

String showChapterSelectionSheet(
      BuildContext context,
      List<ChapterModel> chapter_list,
      String chapter_name,
      final Function(String) onChapterChanged) {
    
    String retValue = chapter_name;
    showModalBottomSheet(
    context: context,
    backgroundColor: Colors.transparent,
    elevation: 0,
    isScrollControlled: true,
    shape: RoundedRectangleBorder(
      borderRadius: BorderRadius.only(
          topLeft: Radius.circular(20), topRight: Radius.circular(20)),
    ),
    builder: (context) {
      return StatefulBuilder(
        builder: (BuildContext context,
            StateSetter setState /*You can rename this!*/) {
          return makeDismissible(
            context,
            child: DraggableScrollableSheet(
              initialChildSize: 0.81,
              minChildSize: 0.5,
              maxChildSize: 0.81,
              builder: (_, controller) => Container(
                padding: EdgeInsets.all(getProportionateScreenWidth(25)),
                height: getProportionateScreenWidth(600),
                decoration: BoxDecoration(
                  color: backgroundColor2,
                  borderRadius: BorderRadius.vertical(top: Radius.circular(20)),
                ),
                child: Column(
                  children: [
                    Padding(
                      padding: EdgeInsets.only(
                          top: getProportionateScreenHeight(32),
                          bottom: getProportionateScreenHeight(16)),
                      child: Text(
                        AppLocalizations.of(context)!.chapters,
                        style: Theme.of(context)
                            .textTheme
                            .headline2!
                            .apply(color: Colors.white),
                      ),
                    ),
                    Expanded(
                      child: ListView.builder(
                        shrinkWrap: true,
                        controller: controller,
                        itemCount: chapter_list.length,
                        itemBuilder: (_, index) {
                          return GestureDetector(
                            child: Padding(
                              padding: EdgeInsets.only(
                                  top: getProportionateScreenHeight(8)),
                              child: Card(
                                child: Container(
                                  height: getProportionateScreenHeight(56),
                                  width: getProportionateScreenWidth(341),
                                  decoration: BoxDecoration(
                                    border: Border.all(color: cardColor),
                                    color: chapter_list[index].chapter_name! ==
                                        chapter_name
                                        ? backgroundColor
                                        : cardColor,
                                  ),
                                  child: Padding(
                                    padding: EdgeInsets.all(0),
                                    child: Center(
                                      child: Row(
                                        children: [
                                          Container(
                                              width:
                                              getProportionateScreenWidth(
                                                  32),
                                              child: chapter_list[index]
                                                  .chapter_name! ==
                                                  chapter_name
                                                  ? Icon(
                                                Icons.check,
                                                color: brandYellow,
                                              )
                                                  : SizedBox()),
                                          Text(
                                            "Chapter ${chapter_list[index].position!}: ",
                                            style: Theme.of(context)
                                                .textTheme
                                                .bodyText2!
                                                .apply(color: brandYellow),
                                          ),
                                          Expanded(
                                            child: Text(
                                                chapter_list[index]
                                                    .chapter_name!,
                                                style: Theme.of(context)
                                                    .textTheme
                                                    .bodyText2!
                                                    .apply(
                                                    color: chapter_list[
                                                    index]
                                                        .chapter_name! ==
                                                        chapter_name
                                                        ? tertiaryTextColor
                                                        : primaryTextColor)),
                                          ),
                                        ],
                                      ),
                                    ),
                                  ),
                                ),
                              ),
                            ),
                            onTap: () {
                              onChapterChanged(chapter_list[index].chapter_name!);
                              setState(() {
                                 retValue = chapter_list[index].chapter_name!;
                              });
                              Navigator.pop(context);
                            },
                          );
                        },
                      ),
                    ),
                  ],
                ),
              ),
            ),
          );
        },
      );
    },
  );
    return retValue;
}

And I am accessing it here -

return InkWell(
    onTap: () async {
    if(dataList.isNotEmpty) {
         chapterName.value = showChapterSelectionSheet(
             context,dataList,chapterName.value,(val) {
                setState(() {
                    chapterName.value = val;
                    print("Val is - $val");
                });
             }
         );
      }
   },
   child: .....
);

In the above InkWell, the print statement is working fine but value is not changing.

And I want to update and use the value here -

child: ValueListenableBuilder(
   valueListenable: chapterName,
   builder: (context, String val, Widget? child) {
       return Text(
          val,
          style: TextStyle(
             color: Colors.white,
             fontSize: 15,
          ),
        );
   },
),


Solution 1:[1]

It is possible you are just missing await before await showModalBottomSheet(..).

You can follow this simplified snippet.

class BVChange extends StatefulWidget {
  const BVChange({Key? key}) : super(key: key);

  @override
  State<BVChange> createState() => _BVChangeState();
}

class _BVChangeState extends State<BVChange> {
  String var1 = "Old", var2 = "old1";

  Future<String> _showDialog(String v) async {
    double _sliderValue = 0.0;
    await showModalBottomSheet(
        context: context,
        builder: (_) {
          return StatefulBuilder(
            builder: (context, sbSate) => Column(
              children: [
                Text(_sliderValue.toString()),
                Slider(
                    value: _sliderValue,
                    onChanged: (sval) {
                      sbSate(() {
                        _sliderValue = sval;
                      });
                    }),
              ],
            ),
          );
        });

    return _sliderValue.toString();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Column(
        children: [
          GestureDetector(
              onTap: () async {
                final data = await _showDialog(var1);

                setState(() {
                  var1 = data;
                });
              },
              child: Text("var1  : $var1")),
          GestureDetector(
            onTap: () async {
              final data = await _showDialog(var2);
              setState(() {
                var2 = data;
              });
            },
            child: Text("var 2 : $var2"),
          ),
        ],
      ),
    );
  }
}

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Yeasin Sheikh