Flutter: Calling SetState() from another class

9,313

It simple, you need to send your SinglePlayMode::toggleCoin function as callback to dropDownMenu class.

class dropDownMenu extends StatefulWidget {  
        final _callback; // callback reference holder
                                   //you will pass the callback here in constructor
    dropDownMenu( {@required void toggleCoinCallback() } ) :
       _callback = toggleCoinCallback;
        @override
      _dropDownMenuState createState() => _dropDownMenuState();
    }

    class _dropDownMenuState extends State<dropDownMenu> {
      @override
      Widget build(BuildContext context) {
        return Stack(
          children: <Widget> [
            Column(
              mainAxisAlignment: MainAxisAlignment.end,
              children: <Widget>[
                Container(
                  child: Opacity(
                    opacity: 0.0,
                    child: FloatingActionButton(
                      heroTag: null,
                      onPressed:  (){
                        widget?._callback(); // callback calling
                      },
                    ),
                  ),
              );
           }
      }

Then when you create a dropDownMenu class instance in your SinglePlayerMode class you will do

    dropDownMenu(
       toggleCoinCallback: toogleCoin,
    );
Share:
9,313
Bisclavret
Author by

Bisclavret

Updated on December 05, 2022

Comments

  • Bisclavret
    Bisclavret over 1 year

    I am trying to make a simple image that appears or disappears when a button is pushed. This button resides in a separate class to the image, so in Flutter this creates a massive headache of an issue.

    I have read many forums on this and I have tried all the solutions posed but none of them are working for me.

    What I am trying to do:

    class SinglePlayerMode extends StatefulWidget {
      @override
      SinglePlayerModeParentState createState() => SinglePlayerModeParentState();
    }
    
    class SinglePlayerModeParentState extends State<SinglePlayerMode> {\
      bool coinVisible = false;
    
      toggleCoin() {
        setState(() {
          coinVisible = !coinVisible;
        });
      }
    
    Widget topMenuRow() {
      return Stack(
        children: [
          Column(
            children: [
              coinVisible == true ?
              Padding(
                padding: EdgeInsets.all(50),
                child: Container(
                  height: 60,
                  width: 60,
                  color: Colors.blueGrey[0],
                  decoration: BoxDecoration(
                    color: Colors.blueAccent,
                    image: DecorationImage(
                      image: ExactAssetImage('lib/images/coin_head.jpg'),
                      fit: BoxFit.cover,
                    ),
                  ),
                ),
              ) : Container(
                height: 60,
                width: 60,
                color: Colors.black,
              ),
            ],
          ),
        ],
      );
     }
    
    @override
    Widget build(BuildContext context) {
      return Scaffold(
          child: ListView(
            padding: EdgeInsets.symmetric(horizontal: 10.0, vertical: 10.0),
            children: [
              topMenuRow(),
              SizedBox(height: 40),
            ],
          ),
        ),
      );
    }
    

    And this is the separate class which I would like to trigger the SetState() on coinVisible from:

    class dropDownMenu extends StatefulWidget {  @override
      _dropDownMenuState createState() => _dropDownMenuState();
    }
    
    class _dropDownMenuState extends State<dropDownMenu> {
      @override
      Widget build(BuildContext context) {
        return Stack(
          children: <Widget> [
            Column(
              mainAxisAlignment: MainAxisAlignment.end,
              children: <Widget>[
                Container(
                  child: Opacity(
                    opacity: 0.0,
                    child: FloatingActionButton(
                      heroTag: null,
                      onPressed:  (){
                        //SOMEHOW CALL SetState() ON coinVisble HERE!
                      },
                    ),
                  ),
              );
           }
      }
    

    But nothing I have tried is working, and I have lost hours.

  • Bisclavret
    Bisclavret about 5 years
    Oh my god! You are my actual hero. Thank you so much, Marcos.
  • Bisclavret
    Bisclavret about 5 years
    As an add-on to this, dropDownMenu is a menu of many buttons. How can I add an additional callback to this class? I need to be able to use many different callbacks. Is this possible?
  • Marcos Boaventura
    Marcos Boaventura about 5 years
    Well depends of your needs. By example, if you need a small number of callbacks like 2,3, 4, i advise you use the same approach that i already showed. You will only need pass the callbacks as parameters in constructor class, hold the callbacks into a class member and call when you want.
  • Bisclavret
    Bisclavret about 5 years
    Thanks for the reply Marcos. Any chance you can show me in code? I am trying to do this but I have no idea how. Nothing I am trying is working.
  • Marcos Boaventura
    Marcos Boaventura about 5 years
    Yes I can do latter. Just explain with more details what's your needs.
  • Bisclavret
    Bisclavret about 5 years
    I got it working mate, I was trying to call the parameters in the wrong class. I worked out how to call these from the child class and then create a case statement to handle each particular button call. Thanks again, Marcos!
  • Marcos Boaventura
    Marcos Boaventura about 5 years
    I am glad for this.
  • Aayush Neupane
    Aayush Neupane over 4 years
    why is it void in dropdown menu constructor? mine didn't worked with void but worked without it instead