flutterdart

Troubleshooting Flutter Button Color Issue: Selected Background Color Not Applying as Expected


Certainly, here's the updated query question with the actual result you're experiencing:

"I'm working on a Flutter app with a custom InputButton widget that allows users to select items. When an item is selected, the button's background color should change to a specified color (isSelectedBgColor) and the text color should also change (isSelectedTextColor). However, even though I've set the background color to Colors.blue.shade300 and the text color to the desired value, the button's background color appears gray when selected. I've confirmed that the _StudenceInputButtonState widget is being rebuilt when the button is clicked. Despite this, the selected background color is not being applied as expected, and the button's appearance remains unchanged. How can I troubleshoot and resolve this issue to make sure the selected colors are applied correctly to the button's background and text?

  class InputButton extends StatefulWidget {
  late final Color backgroundColor;
  late final Color textColor;
  final Color isSelectedBgColor; // New parameter for selected background color
  final Color isSelectedTextColor; // New parameter for selected text color
  final double height;
  final double width;
  final double borderRadius;
  final List<dynamic> itemList;
  final ValueNotifier<bool> controller;
  final bool isVisible;
  final ButtonAlignment alignment;
  final double buttonSpacing;

  InputButton({
    required this.backgroundColor,
    required this.textColor,
    required this.isSelectedBgColor,
    required this.isSelectedTextColor,
    required this.height,
    required this.width,
    required this.borderRadius,
    required this.itemList,
    required this.controller,
    this.isVisible = true,
    this.alignment = ButtonAlignment.HORIZONTAL,
    this.buttonSpacing = 10.0,
  });

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

class _InputButtonState extends State<InputButton> {
  static final Map<String, bool> buttonSelections = {};
  bool isAnyButtonSelected = true;

  @override
  void initState() {
    super.initState();

    // Initialize buttonSelections map
    for (var item in widget.itemList) {
      buttonSelections[item.name] = false;
    }
    if (widget.itemList.isNotEmpty) {
      buttonSelections[widget.itemList[0].name] = true;
    }
  }

  @override
  Widget build(BuildContext context) {
    print("Widget is being rebuilt!");
    return Visibility(
      visible: widget.isVisible,
      child: widget.alignment == ButtonAlignment.horizontal
          ? Row(
              children: _buildButtons(),
            )
          : Column(
              children: _buildButtons(),
            ),
    );
  }

  List<Widget> _buildButtons() {
    List<Widget> buttons = [];
    for (var item in widget.itemList) {
      String label = item.name;
      Color borderColor = widget.isSelectedBgColor;
      buttons.add(
        SizedBox(
          height: widget.height,
          width: widget.width,
          child: ElevatedButton(
            onPressed: getButtonSelection(label)
                ? null
                : () async {
                    setState(() {
                      setButtonSelection(label);
                    });
                  },
            style: ElevatedButton.styleFrom(
              textStyle:
                  TextStyle(color: getTextColor(getButtonSelection(label))),
              backgroundColor: getBgColor(getButtonSelection(label)),
              foregroundColor: getTextColor(getButtonSelection(label)),
              shape: RoundedRectangleBorder(
                borderRadius: BorderRadius.circular(widget.borderRadius),
                side: BorderSide(color: borderColor),
              ),
            ),
            child: ValueListenableBuilder<bool>(
              valueListenable: widget.controller,
              builder: (context, isLoading, child) {
                if (isLoading) {
                  return Row(
                    mainAxisAlignment: MainAxisAlignment.center,
                    children: [
                      SizedBox(
                        width: 20,
                        height: 20,
                        child: CircularProgressIndicator(
                          color: getTextColor(getButtonSelection(label)),
                        ),
                      ),
                      SizedBox(width: 10),
                      Text(
                        label,
                        style: TextStyle(
                            color: getTextColor(getButtonSelection(label))),
                      ),
                    ],
                  );
                } else {
                  return Text(
                    label,
                    style: TextStyle(
                        color: getTextColor(getButtonSelection(label))),
                  );
                }
              },
            ),
          ),
        ),
      );

      // Add spacing between buttons
      if (widget.alignment == ButtonAlignment.horizontal) {
        buttons.add(SizedBox(width: widget.buttonSpacing));
      } else {
        buttons.add(SizedBox(height: widget.buttonSpacing));
      }
    }

    return buttons;
  }

  void setButtonSelection(String selectedKey) {
    setState(() {
      for (String key in buttonSelections.keys) {
        buttonSelections[key] = key == selectedKey;
      }
    });
  }

  bool getButtonSelection(String label) {
    return buttonSelections[label]!;
  }

  void _handleButtonPressed(String label) {
    print("Button with label '$label' pressed.");
    // Perform action based on the pressed button label
  }

  Color getBgColor(bool buttonSelection) {
    if (buttonSelection) {
      print(widget.isSelectedBgColor);
      return Colors.blue.shade300;
    } else {
      return widget.backgroundColor;
    }
  }

  Color getTextColor(bool buttonSelection) {
    if (buttonSelection) {
      return widget.isSelectedTextColor;
    } else {
      return widget.textColor;
    }
  }
}

i want to get the button colors changes when the user click on button


Solution

  • After carefully researching a few things, I got this solution. Try it.

    Replace ElevatedButton.styleFrom with ButtonStyle, setting backgroundColor conditionally using MaterialStateProperty.resolveWith for normal and pressed states.

    style: ButtonStyle(
      textStyle: WidgetStateProperty.all<TextStyle>(
        TextStyle(color: getTextColor(getButtonSelection(label))),
      ),
      backgroundColor: WidgetStateProperty.resolveWith<Color>(
        (Set<WidgetState> states) {
          if (states.contains(WidgetState.pressed) ||
              getButtonSelection(label)) {
            return widget.isSelectedBgColor;
          }
          return widget.backgroundColor;
        },
      ),
      shape: WidgetStateProperty.all<OutlinedBorder>(
        RoundedRectangleBorder(
          borderRadius: BorderRadius.circular(widget.borderRadius),
          side: BorderSide(
            color: getButtonSelection(label)
                ? widget.isSelectedBgColor
                : widget.backgroundColor,
          ),
        ),
      ),
    ),