Home > other >  How to refresh the parent widget when I change data from a Modal Bottomsheet?
How to refresh the parent widget when I change data from a Modal Bottomsheet?

Time:11-26

Hello I try to refresh _currentValue when I open a modal bottom sheet and I change the value from state full widget depense().

Here is my code

new RaisedButton(
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(10)),
elevation: 5,
highlightElevation: 10,
color: Colors.white,
splashColor: Colors.white,
    child :  new  Text("${_currentValue}",textAlign: TextAlign.center,  style: TextStyle(color: Colors.black, fontWeight: FontWeight.w400, fontSize:  SizeConfig.safeBlockHorizontal! * 4)),
        padding: const EdgeInsets.all (15.0),
        onPressed: () {
        setState(() {
        showMaterialModalBottomSheet(isDismissible: true,
        shape:  RoundedRectangleBorder(
        borderRadius:
        BorderRadius.circular(15)),
        context: context,
        builder: (context) => depense()
          );
          });
          }),

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

  @override
  State<depense> createState() => _depenseState();
}

class _depenseState extends State<depense> {

  int _currentValue = 5;
 
  @override
  void initState() {
    // TODO: implement initState
    super.initState();
  }

  @override
  Widget build(BuildContext context) {
    return  Container(
        width: MediaQuery.of(context).size.width/1,
        height: MediaQuery.of(context).size.height/1.8,
        child :
        Padding(
            padding: const EdgeInsets.only(left:20,right:20),
            child:
          
              Container(
                alignment: Alignment.center,
                child: NumberPicker(
                  axis: Axis.horizontal,
                  itemHeight: 70,
                  itemWidth: 70,
                  step: 1,
                  selectedTextStyle: const TextStyle(
                    fontSize: 30.0,
                    color: Color(0xff61d3cb),
                    fontWeight: FontWeight.w800,
                  ),
                  textStyle: const TextStyle(
                    color: Colors.black,
                    fontSize: 12.0,
                  ),
                  value: _currentValue,
                  minValue: 0,
                  maxValue: 1000,

                  onChanged: (v) {
                    setState(() {
                      _currentValue = v;

                    });
                  },
                ),
              ),
             
            ));
  }
}

If I add the widget build from depense state full widget directly on the modalbottomsheet like bellow, Text("${_currentValue}" is upgrade but NumberPicker return to initial value... But when I create the statefull widget I can use NumberPicker but not refresh data...

 new RaisedButton(

  shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(10)),
  elevation: 5,
  highlightElevation: 10,
  color: Colors.white,
  splashColor: Colors.white,
  child :  new  Text("${_currentValue}",textAlign: TextAlign.center,  style: TextStyle(color: Colors.black, fontWeight: FontWeight.w400, fontSize:  SizeConfig.safeBlockHorizontal! * 4)),
  padding: const EdgeInsets.all (15.0),
  onPressed: () {


setState(() {
  showMaterialModalBottomSheet(isDismissible: true,
      shape:  RoundedRectangleBorder(
          borderRadius:
          BorderRadius.circular(15)),

      context: context,
      builder: (context) =>  Container(


          width: MediaQuery.of(context).size.width/1,
          height: MediaQuery.of(context).size.height/1.8,

          child :
          Padding(
              padding: const EdgeInsets.only(left:20,right:20),
              child:
           
                      Container(
                        alignment: Alignment.center,
                        child: NumberPicker(
                          axis: Axis.horizontal,
                          itemHeight: 70,
                          itemWidth: 70,
                          step: 1,
                          selectedTextStyle: const TextStyle(
                            fontSize: 30.0,
                            color: Color(0xff61d3cb),
                            fontWeight: FontWeight.w800,
                          ),
                          textStyle: const TextStyle(
                            color: Colors.black,
                            fontSize: 12.0,
                          ),
                          value: _currentValue,
                          minValue: 0,
                          maxValue: 1000,

                          onChanged: (v) {
                            setState(() {
                              _currentValue = v;

                            });
                          },
                        ),
                      ),
          ))
  );
});

                                      }),

CodePudding user response:

You need define currentValue in your main class and pass a function to depense class like this:

class depense extends StatefulWidget {
  final Function(int) onChange; //<-- add this
  const depense({Key? key, required this.onChange}) : super(key: key);

  @override
  State<depense> createState() => _depenseState();
}

class _depenseState extends State<depense> {
  int _currentValue = 5;
  @override
  Widget build(BuildContext context) {
    return Container(
        width: MediaQuery.of(context).size.width / 1,
        height: MediaQuery.of(context).size.height / 1.8,
        child: Padding(
          padding: const EdgeInsets.only(left: 20, right: 20),
          child: Container(
            alignment: Alignment.center,
            child: NumberPicker(
              axis: Axis.horizontal,
              itemHeight: 70,
              itemWidth: 70,
              step: 1,
              selectedTextStyle: const TextStyle(
                fontSize: 30.0,
                color: Color(0xff61d3cb),
                fontWeight: FontWeight.w800,
              ),
              textStyle: const TextStyle(
                color: Colors.black,
                fontSize: 12.0,
              ),
              value: _currentValue,
              minValue: 0,
              maxValue: 1000,
              onChanged: (v) {
                widget.onChange(v);
                setState(() {
                  _currentValue = v;
                });
              },
            ),
          ),
        ));
  }
}

Then you use it like this:

 RaisedButton(
      shape: RoundedRectangleBorder(
          borderRadius: BorderRadius.circular(10)),
      elevation: 5,
      highlightElevation: 10,
      color: Colors.white,
      splashColor: Colors.white,
      child: new Text("${_currentValue}",
          textAlign: TextAlign.center,
          style: TextStyle(
              color: Colors.black,
              fontWeight: FontWeight.w400,
              fontSize: SizeConfig.safeBlockHorizontal! * 4)),
      padding: const EdgeInsets.all(15.0),
      onPressed: () {
        setState(() {
          showMaterialModalBottomSheet(
              isDismissible: true,
              shape: RoundedRectangleBorder(
                  borderRadius: BorderRadius.circular(15)),
              context: context,
              builder: (context) => depense(onChange:(value){
                 setState(() {
                     _currentValue = value;
                 });
              }));
        });
      })

CodePudding user response:

It looks like _currentValue is a local state variable of the dispense class and you have another variable by same name in parent class also. Changes in local state variables are not reflected in parent widgets.

Usually, you should use any state management libraries in such scenarios, but a simple solution can be to pass a callback function from RaisedButton to dispense widget which will return its value.

class depense extends StatefulWidget {
   Function changeCurrentValue(int val);

  const depense({Key? key}) : super(key: key);

  @override
  State<depense> createState() => _depenseState();
}

class _depenseState extends State<depense> {
   ...

    @override
  Widget build(BuildContext context) {
    return  Container(
        width: MediaQuery.of(context).size.width/1,
        height: MediaQuery.of(context).size.height/1.8,
        child :
        ...
        onChanged: (v) {
           widget.changeCurrentValue(v);
       }

In RaisedButton

int _currentValue = 5;

void changeCurrentValue(int v){
   setState(() {
       _currentValue = v;
    })
}

new RaisedButton(
   ...
   showMaterialModalBottomSheet(isDismissible: true,
        shape:  RoundedRectangleBorder(
        borderRadius:
        BorderRadius.circular(15)),
        context: context,
        builder: (context) => depense(changeCurrentValue: changeCurrentValue)
    ....

   


   
  • Related