Salim Azeri
Salim Azeri

Reputation: 53

Switching between buttons state in flutter

I'm making simple flutter app with three custom buttons, when im clicking on one button it change background color on this button. What i want to achieve is when i am clicking on button when other button is activated i want to deactivate button and activate button that i just clicked. Custom button is represented by CircleButton class and im using three of these in my main build in HomePageClass.

I wonder where it should be to turn off and turn on the appropriate buttons, it seems to me that everything should be handled in the CircleButton class.

Circle button class:

class CircleButton extends StatefulWidget {
  final VoidCallback onPressed;
  final String imageData;
  final String buttonName;
  CircleButton({this.onPressed, this.imageData, this.buttonName});
  @override
  _CircleButtonState createState() => _CircleButtonState();
}

class _CircleButtonState extends State<CircleButton> {
  bool _active = false;
  //bool isButtonActive = false;
  void handleTap() {
    setState(() {
      /*
      if(widget.buttonName == 'Mode'){
      }
      if(widget.buttonName =='Sounds'){
      }
      if(widget.buttonName =='Volume'){
      }
      isButtonActive = !isButtonActive;
      */
      _active = !_active;
      widget.onPressed();
    });
    //print('widget.isActive:' + isButtonActive.toString());
  }

  @override
  Widget build(BuildContext context) {
    double circleBoxSize = 50.0;
    return new Column(
      children: <Widget>[
        FlatButton(
          splashColor: Colors.transparent,
          highlightColor: Colors.transparent,
          onPressed: handleTap,
          child: new Container(
            width: circleBoxSize,
            height: circleBoxSize,
            decoration: new BoxDecoration(
                gradient: _active
                    ? LinearGradient(
                        begin: Alignment.bottomLeft,
                        end: Alignment.topRight,
                        colors: [
                            Color.fromRGBO(79, 172, 254, 1),
                            Color.fromRGBO(0, 242, 245, 1)
                          ])
                    : null,
                shape: BoxShape.circle,
                color: _active ? null : Color.fromRGBO(227, 230, 238, 1)),
            child: new Image.asset(
              this.widget.imageData,
              color: _active ? Color.fromRGBO(255, 255, 255, 1) : null,
              scale: 1.8,
            ),
          ),
        ),
        SizedBox(height: 14),
        new Text(
          this.widget.buttonName,
          style: TextStyle(
              fontFamily: "Roboto",
              fontSize: 14,
              color: Color.fromRGBO(140, 151, 173, 1),
              fontWeight: FontWeight.normal),
        )
      ],
    );
  }
}

HomePage where i'm using CircleButton objects:

class _HomePageState extends State<HomePage> {
  bool _active = false;
  int iter = 0;
  String activeButton;
  List<String> selectBarData = ['dasdasdas'];
  List<String> modes = ['deep-sleep', 'pain-relief'];
  List<String> sounds = ['campfire', 'rain'];

  void handleButtonsPress(){
    setState(){

    }
  }


  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
          body: Column(
        children: <Widget>[
          Container(
              padding: EdgeInsets.only(left: 25, right: 25, top: 60),
              child: Row(
                mainAxisAlignment: MainAxisAlignment.spaceBetween,
                children: <CircleButton>[
                  new CircleButton(
                    onPressed: handleButtonsPress,
                    imageData: 'assets/body-organ.png',
                    buttonName: 'Mode',
                  ),
                  new CircleButton(
                    onPressed: handleButtonsPress,
                    imageData: 'assets/audio.png',
                    buttonName: 'Sounds',
                  ),
                  new CircleButton(
                    onPressed: handleButtonsPress,
                    imageData: 'assets/speaker.png',
                    buttonName: 'Volume',
                  )
                ],
              )),
          selectBar()
        ],
      )),
    );
  }
}

when im starting app and im clicking first button it looks like that:

enter image description here

when im clicking second button it looks like that:

enter image description here

but i want result like that:

enter image description here

Upvotes: 1

Views: 4642

Answers (1)

Anthony Sette
Anthony Sette

Reputation: 837

I didn't have an opportunity to test this but it should work. I created a ValueChange callback that returns the assigned tag of the button to the parent. This allows you to change the state (active or not) of the button based on whether the _active is equivalent to the tag of the button. Hopefully, this makes sense. Here is the code, there are comments in some of the parts I changed. If you have any questions or problems let me know!

Home:

class _HomePageState extends State<HomePage> {
  String _active;
  int iter = 0;
  String activeButton;
  List<String> selectBarData = ['dasdasdas'];
  List<String> modes = ['deep-sleep', 'pain-relief'];
  List<String> sounds = ['campfire', 'rain'];

  // ValueChanged<String> callback
  void active(String btn) {
    setState(() => _active = btn);
  }


  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
          body: Column(
        children: <Widget>[
          Container(
              padding: EdgeInsets.only(left: 25, right: 25, top: 60),
              child: Row(
                mainAxisAlignment: MainAxisAlignment.spaceBetween,
                children: <CircleButton>[
                  new CircleButton(
                    action: active, //pass data from child to parent
                    tag: "button1", //specifies attribute of button
                    active: _active == "button1" ? true : false, //set button active based on value in this parent
                    imageData: 'assets/body-organ.png',
                    buttonName: 'Mode',
                  ),
                  new CircleButton(
                    action: active,
                    tag: "button2",
                    active: _active == "button2" ? true : false,
                    imageData: 'assets/audio.png',
                    buttonName: 'Sounds',
                  ),
                  new CircleButton(
                    action: active,
                    tag: "button3",
                    active: _active == "button2" ? true : false,
                    imageData: 'assets/speaker.png',
                    buttonName: 'Volume',
                  )
                ],
              )),
          selectBar()
        ],
      )),
    );
  }
}

Button:

class CircleButton extends StatefulWidget {
  final ValueChanged<String> action; //callback value change
  final String tag; //tag of button
  final String imageData;
  final String buttonName;
  final bool active; // state of button
  CircleButton({this.action, this.imageData, this.buttonName, this.active, this.tag});
  @override
  _CircleButtonState createState() => _CircleButtonState();
}

class _CircleButtonState extends State<CircleButton> {
  void handleTap() {
    setState(() {
      widget.action(widget.tag);
    });
  }

  @override
  Widget build(BuildContext context) {
    double circleBoxSize = 50.0;
    return new Column(
      children: <Widget>[
        FlatButton(
          splashColor: Colors.transparent,
          highlightColor: Colors.transparent,
          onPressed: handleTap,
          child: new Container(
            width: circleBoxSize,
            height: circleBoxSize,
            decoration: new BoxDecoration(
                gradient: widget.active
                    ? LinearGradient(
                        begin: Alignment.bottomLeft,
                        end: Alignment.topRight,
                        colors: [
                            Color.fromRGBO(79, 172, 254, 1),
                            Color.fromRGBO(0, 242, 245, 1)
                          ])
                    : null,
                shape: BoxShape.circle,
                color: widget.active ? null : Color.fromRGBO(227, 230, 238, 1)),
            child: new Image.asset(
              this.widget.imageData,
              color: widget.active ? Color.fromRGBO(255, 255, 255, 1) : null,
              scale: 1.8,
            ),
          ),
        ),
        SizedBox(height: 14),
        new Text(
          this.widget.buttonName,
          style: TextStyle(
              fontFamily: "Roboto",
              fontSize: 14,
              color: Color.fromRGBO(140, 151, 173, 1),
              fontWeight: FontWeight.normal),
        )
      ],
    );
  }
}

Hopefully, this is helpful!

Upvotes: 1

Related Questions