Home > Back-end >  How to make one button visible when another is clicked in Flutter/Dart?
How to make one button visible when another is clicked in Flutter/Dart?

Time:07-05

I know how to make elements visible or invisible using the Visibility widget. Here is my code:

// New Game route
class NewGameRoute extends StatelessWidget {
  const NewGameRoute({key});

  @override
  Widget build(BuildContext context) {
    return const MaterialApp(
      debugShowCheckedModeBanner: false,
      title: 'New Game',
      home: ListFromCSV1(),
    );
  }
}

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

  @override
  _ListFromCSVState1 createState() => _ListFromCSVState1();
}

class _ListFromCSVState1 extends State<ListFromCSV1> {
  List<List<dynamic>> _listData = [
    [""]
  ];
  int _listCount = 0;
  bool _isFirstLoad = true;
  String assetPath = "files/main.jpg";

  @override
  void initState() {
    _loadCSV();
  }

  // This function is only triggered at init, so we only load csv once
  void _loadCSV() async {
    String rawData = await rootBundle.loadString("files/Text.csv");
    _listData = const CsvToListConverter().convert(rawData);
    assetPath = _listData[_listCount][1] == ""
        ? "files/main.jpg"
        : _listData[_listCount][1];
  }

  // This function is triggered when my button is pressed
  void _nextCSV() {
    setState(() {
      _listData = _listData;
      _listCount < _listData.length - 1
          ? _isFirstLoad
          ? _isFirstLoad = false
          : _listCount  
          : _listCount;
      assetPath =
      _listData[_listCount][1] == "" ? assetPath : _listData[_listCount][1];
    });
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('New Game'),
      ),
      body: Container(
        height: MediaQuery.of(context).size.height,
        decoration: BoxDecoration(
            image: DecorationImage(
                image: AssetImage(assetPath),
                fit: BoxFit.cover)),
        child: Column(
          mainAxisSize: MainAxisSize.min,
          children: <Widget>[
            Visibility(
              child: Column(
              children: [
                ClipRRect(
                  borderRadius: BorderRadius.circular(4),
                  child: Stack(
                    children: <Widget>[
                      Positioned.fill(
                        child: Container(
                          decoration: BoxDecoration(
                              image: DecorationImage(
                                  image: AssetImage('files/sheet.jpg'),
                                  fit: BoxFit.cover)),
                        ),
                      ),
                      Text(_listData[_listCount][0]),
                    ],
                  ),
                ),
                Row(
                  mainAxisAlignment: MainAxisAlignment.spaceAround,
                  children: [
                    ImageButton(label: 'OK', onButtonTap: _nextCSV),
                    ImageButton(label: 'Hide', onButtonTap: () {}),
                  ],
                ),
              ],
            ),
              visible: true,
            ),
            // your other widgets
            Visibility(
              child: ImageButton(label: 'Show', onButtonTap: () {}),
              visible: false,
            )

          ],
        ),
      ),
    );
  }
}

//Class for a cool button
class ImageButton extends StatelessWidget {
  const ImageButton({Key? key, required this.label, required this.onButtonTap})
      : super(key: key);
  final String label;
  final Function onButtonTap;

  @override
  Widget build(BuildContext context) {
    return InkWell(
      onTap: () => onButtonTap(),
      child: Container(
        // customize you button shape and size and design
        margin: const EdgeInsets.all(8),
        padding: const EdgeInsets.symmetric(vertical: 8, horizontal: 32),
        decoration: const BoxDecoration(
            borderRadius: BorderRadius.all(Radius.circular(2)),
            image: DecorationImage(
                image: AssetImage("files/sheet.jpg"), // you can also pass the image dynamically with variable created for the widget.
                fit: BoxFit.cover)),
        child: Center(
          child: Text(
            label,
            style: const TextStyle(
                color: Colors
                    .black, // you can get dominant colour on image and change the text color accordingly or apply shadows to the text
                fontWeight: FontWeight.w500,
                fontSize: 16),
          ),
        ),
      ),
    );
  }
}

The part with Visible/Invisible elements only:

  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('New Game'),
      ),
      body: Container(
        height: MediaQuery.of(context).size.height,
        decoration: BoxDecoration(
            image: DecorationImage(
                image: AssetImage(assetPath),
                fit: BoxFit.cover)),
        child: Column(
          mainAxisSize: MainAxisSize.min,
          children: <Widget>[
            Visibility(
              child: Column(
              children: [
                ClipRRect(
                  borderRadius: BorderRadius.circular(4),
                  child: Stack(
                    children: <Widget>[
                      Positioned.fill(
                        child: Container(
                          decoration: BoxDecoration(
                              image: DecorationImage(
                                  image: AssetImage('files/sheet.jpg'),
                                  fit: BoxFit.cover)),
                        ),
                      ),
                      Text(_listData[_listCount][0]),
                    ],
                  ),
                ),
                Row(
                  mainAxisAlignment: MainAxisAlignment.spaceAround,
                  children: [
                    ImageButton(label: 'OK', onButtonTap: _nextCSV),
                    ImageButton(label: 'Hide', onButtonTap: () {}),
                  ],
                ),
              ],
            ),
              visible: true,
            ),
            // your other widgets
            Visibility(
              child: ImageButton(label: 'Show', onButtonTap: () {}),
              visible: false,
            )

          ],
        ),
      ),
    );
  }
}

//Class for a cool button
class ImageButton extends StatelessWidget {
  const ImageButton({Key? key, required this.label, required this.onButtonTap})
      : super(key: key);
  final String label;
  final Function onButtonTap;

  @override
  Widget build(BuildContext context) {
    return InkWell(
      onTap: () => onButtonTap(),
      child: Container(
        // customize you button shape and size and design
        margin: const EdgeInsets.all(8),
        padding: const EdgeInsets.symmetric(vertical: 8, horizontal: 32),
        decoration: const BoxDecoration(
            borderRadius: BorderRadius.all(Radius.circular(2)),
            image: DecorationImage(
                image: AssetImage("files/sheet.jpg"), // you can also pass the image dynamically with variable created for the widget.
                fit: BoxFit.cover)),
        child: Center(
          child: Text(
            label,
            style: const TextStyle(
                color: Colors
                    .black, // you can get dominant colour on image and change the text color accordingly or apply shadows to the text
                fontWeight: FontWeight.w500,
                fontSize: 16),
          ),
        ),
      ),
    );
  }
}

But how to make a class to do the following:

  1. First my screen looks like this:

enter image description here

  1. When I click on the Hide button, it looks like this:

enter image description here

  1. When I click on the Show button, it looks like this again:

enter image description here

That is, when these buttons are clicked, the visible values for the Column and ImageButton should change from true to false and vice versa.

CodePudding user response:

Replace your code with below code :

class NewGameRoute extends StatefulWidget {
  const NewGameRoute({Key? key, required this.title}) : super(key: key);

  final String title;

  @override
  State<NewGameRoute> createState() => _NewGameRouteState();
}

class _NewGameRouteState extends State<NewGameRoute> {
  bool isPressed = false;

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(widget.title),
      ),
      body: Container(
          padding: EdgeInsets.all(20),
          child: Column(
            children: [
              isPressed == false ? hideButton() : showButton(),
            ],
          )),
    );
  }

  Widget hideButton() {
    return Column(
      children: <Widget>[
        Text('Text1 aaaa aaaaa aaaa aaaa',
            style: TextStyle(backgroundColor: Colors.grey)),
        Row(
          mainAxisAlignment: MainAxisAlignment.spaceEvenly,
          children: [
            ElevatedButton(
              onPressed: () {},
              child: Text(
                'OK',
                style: TextStyle(
                  fontSize: 20,
                ),
              ),
            ),
            ElevatedButton(
              onPressed: () {
                setState(() {
                  isPressed = true;
                });
              },
              child: Text(
                'Hide',
                style: TextStyle(
                  fontSize: 20,
                ),
              ),
            ),
          ],
        )
      ],
    );
  }

  Widget showButton() {
    return Row(
      mainAxisAlignment: MainAxisAlignment.spaceEvenly,
      children: [
        Expanded(
          child: ElevatedButton(
            onPressed: () {
              setState(() {
                isPressed = false;
              });
            },
            child: Text(
              'Show',
              style: TextStyle(
                fontSize: 20,
              ),
            ),
          ),
        ),
      ],
    );
  }
}

CodePudding user response:

I found the simplest solution:

  1. Add this before the widget creating the screen:

    bool isVisible = true; //will be visible for the first frame

  2. Add function for desired buttons:

    ImageButton(label: 'Hide', onButtonTap: () { setState(() { isVisible = !isVisible; }); }),

  • Related