James Piner
James Piner

Reputation: 329

Visibility won't toggle in flutter?

I've got a gridView where each grid has a FlatButton inside it. The button is supposed to trigger the visibility for another button I have outside the GridView. I've set the state in onPressed to change the bool showCard for everytime the GridView button is pressed. In my print statement, it's saying that it's working, producing true and false each time the button is pressed, but it's not changing the visibility of the other button called 'CheckoutCard()'. Can anyone help me?

import 'package:flutter/material.dart';
import 'package:flutter/painting.dart';
import 'package:bee/Cards/Items%20Card.dart';
import 'package:bee/Constants/Constants.dart';
import 'package:bee/MerchantCategories/My Categories.dart';
import 'package:bee/MenuButtons/Color Changer.dart';
import 'package:bee/Cards/Checkout Card.dart';
import 'package:bee/main.dart';
import 'Basket Menu.dart';

class MyMenu extends StatefulWidget {

  @override
  _MyMenuState createState() => _MyMenuState();

}

class _MyMenuState extends State<MyMenu> {

//  bool showCard = _MyButtonState().showCard;

  @override
  Widget build(BuildContext context) {


    return Scaffold(

      appBar: AppBar(

        brightness: Brightness.light,

        leading: new IconButton(
          icon: new Icon(Icons.arrow_back, color: Colors.black),
          onPressed: () { Navigator.of(context).pop();},
        ),

        backgroundColor: Colors.white,
        title: Padding(
          padding: const EdgeInsets.all(6.0),
          child: Image(image: AssetImage('images/Merchants/My_Image.png'),),
        ),
        elevation: 1.0,
        centerTitle: true,

        actions: <Widget>[
          Padding(
            padding: const EdgeInsets.only(right: 15.0),
            child: IconButton(icon: Icon(Icons.shopping_basket, color: Colors.blue[800],),
            onPressed: (){ Navigator.push(context, MaterialPageRoute(builder: (context){return BasketMenu();})); }
            ),
          ),

        ],
      ),





      body: Stack(
          children: <Widget>[
            Flex(
              direction: Axis.vertical,
              children: <Widget>[
                Expanded(
                  flex: 1,
                  child: Padding(
                    padding: const EdgeInsets.all(5.0),
                    child: Container(
                      child: ListView(children: <Widget>[
                        MyCategories(categoryText: Text('Restaurants', style: categoryTextStyle),),
                        MyCategories(categoryText: Text('Bars', style: categoryTextStyle),),
                        MyCategories(categoryText: Text('Games', style: categoryTextStyle),),

                      ],
                        scrollDirection: Axis.horizontal,
                      ),
                    ),
                  ),
                ),

              Expanded(
                  flex: 10,
                  child: Container(

                    child: GridView.count(

                      crossAxisCount: 2,

                      children: <Widget>[


                        ItemsCard(
                          categoryName: Text('Fast Food', style: secondCategoryTextStyle,),
                          itemText: FastFoodText,
                          priceText: Text('£21.67', style: priceTextStyle,),
                          gridOutline: MyButton(
                            tile: GridTile(
                              child: FastFoodImage,
                          ),
                          ),
                        ),


                        ItemsCard(
                          itemText: SnubbText,
                          priceText: Text('£44.95', style: priceTextStyle,),
                          gridOutline: MyButton(
                            tile: GridTile(
                                child: SnubbImage,
                              ),
                          ),
                        ),


                        ItemsCard(
                          itemText: FreshText,
                          priceText: Text('£41.23', style: priceTextStyle,),
                          gridOutline: MyButton(
                            tile: GridTile(
                                child: FreshImage,
                              ),
                          ),
                        ),


                        Container(),


                      ],
                    ),
                  ),
                ),
              ],
            ),

            Visibility(visible: _MyButtonState().showCard ? _MyButtonState().showCard : !_MyButtonState().showCard, child: CheckoutCard()),

          ],
      ),

    );

  }
}


class MyButton extends StatefulWidget {

  @override
  State<StatefulWidget> createState(){
    return _MyButtonState();
  }

  MyButton({this.tile});
  final GridTile tile;

  bool isVisible = false;
  int itemNumber = 0;

  bool showCheckoutCard(){
    return isVisible = !isVisible;
  }

  int itemCounter(){
    return itemNumber++;
  }

}


class _MyButtonState extends State<MyButton> {

  bool changeColor = false;

  static var myNewButtonClass = MyButton();

  bool showCard = myNewButtonClass.isVisible;

  @override
  Widget build(BuildContext context) {
    return FlatButton(
      shape: Border(bottom: BorderSide(color: changeColor ? Colors.blue[800] : Colors.transparent, width: 3.0)),
      child: widget.tile,
      onPressed: (){
        setState(() {
          changeColor = !changeColor;
          myNewButtonClass.itemCounter();
          print(myNewButtonClass.itemCounter());
          setState(() {
            showCard = !showCard;
            print(showCard);
          });
        });
      },
    );
  }
}

Upvotes: 0

Views: 2500

Answers (2)

You are calling the setState method inside your Button. I don't think it will change the state of your MyMenu widget. I would suggest you to change your Button as following:

class MyButton extends StatelessWidget {
  final Color color;
  final GridTile tile;
  final VoidCallback onPressed;

  const MyButton({Key key, this.color, this.tile, this.onPressed})
      : super(key: key);

  @override
  Widget build(BuildContext context) {
    return FlatButton(
      shape: Border(bottom: BorderSide(color: color)),
      child: tile,
      onPressed: onPressed,
    );
  }
}

After that, you need to declare two variable in your MyMenu widget as follows:

class _MyMenuState extends State<MyMenu> {
  bool changeColor = false;
  bool showCard = false;

  @override
  Widget build(BuildContext context) {
    yourBuildMethod()

In your MyMenu widget you can call button like this:

MyButton(
  tile: GridTile(child: SnubbImage),
  color: changeColor
    ? Colors.blue[800]
    : Colors.transparent,
  onPressed: () {
    setState(() {
      changeColor = !changeColor;
      showCard = !showCard;
    });
  },
),

And now check your Visibility like this:

Visibility(
  visible: showCard,
  child: CheckoutCard(),
)

Now your variables are in your MyMenu widget and you are calling setState function in MyMenu widget. So it will be able to update the state of your widget. I hope this will be helpful for you.

Upvotes: 1

J. S.
J. S.

Reputation: 9635

To trigger a rebuild of your view based when changing the value of a variable you need to use setState. Where you are are changing the value of the isVisible variable, you need to surround it with a setState:

setState(() {
  isVisible = !isVisible;
});

Upvotes: 1

Related Questions