Home > Blockchain >  Flutter - How to change button color on the click and disable other buttons?
Flutter - How to change button color on the click and disable other buttons?

Time:05-08

I have a listview with several green buttons, and I need to change the color of a button to red on click. The problem is that in doing that all the other buttons need to go back to their base color green.

On this example below (working version at result

Create new file and copy the following code and see the result:

class TestPage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      theme: ThemeData.dark().copyWith(
        scaffoldBackgroundColor: Colors.blue[800],
      ),
      debugShowCheckedModeBanner: false,
      home: Scaffold(
        body: Center(
          child: MyButtonList(
            buttons: [
              ButtonData(text: 'Test'),
              ButtonData(text: 'Test'),
              ButtonData(text: 'Test'),
              ButtonData(text: 'Test'),
              ButtonData(text: 'Test'),
            ],
          ),
        ),
      ),
    );
  }
}

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

  final List<ButtonData> buttons;

  @override
  State<MyButtonList> createState() => _MyButtonListState();
}

class _MyButtonListState extends State<MyButtonList> {
  late List<bool> favoriateState;

  @override
  void initState() {
    favoriateState = List.generate(
        widget.buttons.length, (index) => widget.buttons[index].isFavorite);
    super.initState();
  }

  @override
  Widget build(BuildContext context) {
    return Column(
      mainAxisAlignment: MainAxisAlignment.spaceEvenly,
      children: [
        for (var i = 0; i < widget.buttons.length; i  )
          MyWidget(
            text: widget.buttons[i].text,
            onPressed: () {
              for (var j = 0; j < favoriateState.length; j  ) {
                favoriateState[j] = false;
              }
              setState(() {
                favoriateState[i] = true;
                if (widget.buttons[i].onPressed != null) {
                  widget.buttons[i].onPressed!();
                }
              });
            },
            isFavourte: favoriateState[i],
          ),
      ],
    );
  }
}

class ButtonData {
  final String text;
  final Function()? onPressed;
  final bool isFavorite;

  ButtonData({required this.text, this.onPressed, this.isFavorite = false});
}

class MyWidget extends StatelessWidget {
  const MyWidget(
      {Key? key,
      required this.text,
      required this.onPressed,
      this.isFavourte = false})
      : super(key: key);

  final String text;
  final Function()? onPressed;
  final bool isFavourte;
  @override
  Widget build(BuildContext context) {
    return ElevatedButton(
        style: ElevatedButton.styleFrom(
          primary: isFavourte ? Colors.red : Colors.green,
        ),
        onPressed: onPressed,
        child: Text(text));
  }
}

CodePudding user response:

You seem to want to emulate RadioButtons by using TextButtons.

Withing a group of RadioListTile-s only one can be active. And this is what you want to achieve, if I understood you correctly.

May I suggest to use RadioListTile-s instead and then style (or theme) these as you like: Green for inactive Tiles, Red for active Tiles.

The following just demonstrates the usage of RadioListTile, further info on styling active-/nonactive-Tiles can be found easily.

import 'package:flutter/material.dart';

void main() => runApp(const MyApp());

/// main application widget
class MyApp extends StatelessWidget {
  const MyApp({Key? key}) : super(key: key);

  static const String _title = 'Flutter Application';

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: _title,
      home: Scaffold(
        appBar: AppBar(title: const Text(_title)),
        body: const MyStatefulWidget(),
      ),
    );
  }
}

/// stateful widget that the main application instantiates
class MyStatefulWidget extends StatefulWidget {
  const MyStatefulWidget({Key? key}) : super(key: key);

  @override
  State<MyStatefulWidget> createState() => _MyStatefulWidgetState();
}

enum Fruit { apple, banana }

/// private State class that goes with MyStatefulWidget
class _MyStatefulWidgetState extends State<MyStatefulWidget> {
  Fruit? _fruit = Fruit.apple;
  @override
  Widget build(BuildContext context) {
    return Center(
      child: Column(
        children: <Widget>[
          RadioListTile<Fruit>(
            title: const Text('Apple'),
            value: Fruit.apple,
            groupValue: _fruit,
            onChanged: (Fruit? value) {
              setState(() {
                _fruit = value;
              });
            },
          ),
          RadioListTile<Fruit>(
            title: const Text('Banana'),
            value: Fruit.banana,
            groupValue: _fruit,
            onChanged: (Fruit? value) {
              setState(() {
                _fruit = value;
              });
            },
          ),
        ],
      ),
    );
  }
}

Source

https://googleflutter.com/flutter-radiolisttile/

  • Related