Paprika
Paprika

Reputation: 174

Flutter button wont change state from active=true to active=false

I have the following button:

class CircularButtonWithIcon extends StatefulWidget {
  CircularButtonWithIcon({
    Key key,
    @required this.onPress,
    this.padding,
    this.border,
    this.isMore,
    this.marginRight,
    this.marginLeft,
    this.icon,
    this.color,
    this.activeColor,
    this.text,
    this.splashColor,
    this.image,
    this.hasState,
    this.borderColor,
  }) : super(key: key);
  double padding;
  double border;
  double marginRight;
  double marginLeft;
  bool isMore = false;
  Icon icon;
  Image image;
  Color color;
  Color activeColor;
  Color borderColor;
  Widget text;
  Color splashColor;
  final Function onPress;
  Function onHighlightChanged_;
  bool active = false;
  bool hasState;

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

class _CircularButtonWithIconState extends State<CircularButtonWithIcon> {
  @override
  Widget build(BuildContext context) {
    return FittedBox(
        child: Container(
            margin: EdgeInsets.only(
                left: widget.marginLeft ?? 0, right: widget.marginRight ?? 0),
            child: RawMaterialButton(
              onPressed: () {
                setState(() {
                  widget.active = !widget.active;
                });
                if (widget.onPress!=null)
                  widget.onPress();
                print(widget.active);
              },
              fillColor: widget.active
                  ? widget.activeColor ?? widget.color ?? Colors.transparent
                  : widget.color ?? Colors.transparent,
              splashColor: widget.splashColor ?? Colors.grey,
              child: widget.text != null
                  ? Container(
                      child: widget.text,
                    )
                  : widget.image ?? widget.icon,
              //padding: EdgeInsets.all(15.0),
              padding: widget.padding != null
                  ? EdgeInsets.all(widget.padding)
                  : EdgeInsets.all(15.0),
              shape: CircleBorder(
                  side: BorderSide(
                      width: widget.border != null ? widget.border : 2.0,
                      style: BorderStyle.solid,
                      color: widget.borderColor ??
                          Colors.grey)),
            )));
  }
}

for some reason, it never changes state. It always prints true when I press it. It should change between true or false. What am I doing wrong?

Also the color won't change, but this is probably because the state wont change.

I tried many things but I don't know why it happens. It's a steteful widget so its state should be possible to change.

Upvotes: 0

Views: 434

Answers (1)

zhpoo
zhpoo

Reputation: 826

Everything in Widget should be immutable!!! All the fields should be final. You should make a copy of widget.active in _CircularButtonWithIconState, and call setState to change the active in the state class.

import 'package:flutter/material.dart';

class CircularButtonWithIcon extends StatefulWidget {
  CircularButtonWithIcon({
    Key key,
    @required this.onPress,
    this.padding,
    this.border,
    // this.isMore,
    this.active = false,
    this.marginRight,
    this.marginLeft,
    this.icon,
    this.color,
    this.activeColor,
    this.text,
    this.splashColor,
    this.image,
    this.hasState,
    this.borderColor,
    this.onHighlightChanged_,
  }) : super(key: key);
  final double padding;
  final double border;
  final double marginRight;
  final double marginLeft;
  final bool isMore = false;
  final Icon icon;
  final Image image;
  final Color color;
  final Color activeColor;
  final Color borderColor;
  final Widget text;
  final Color splashColor;
  final Function onPress;
  final Function onHighlightChanged_;
  final bool active;
  final bool hasState;

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

class _CircularButtonWithIconState extends State<CircularButtonWithIcon> {
  bool active;

  @override
  void initState() {
    super.initState();
    active = widget.active;
  }

  @override
  Widget build(BuildContext context) {
    return FittedBox(
      child: Container(
        margin: EdgeInsets.only(left: widget.marginLeft ?? 0, right: widget.marginRight ?? 0),
        child: RawMaterialButton(
          onPressed: () {
            setState(() {
              active = !active;    // don't use widget.active
            });
            if (widget.onPress != null) widget.onPress();
            print(active);     // don't use widget.active
          },
          fillColor: active   // don't use widget.active
              ? widget.activeColor ?? widget.color ?? Colors.transparent
              : widget.color ?? Colors.transparent,
          splashColor: widget.splashColor ?? Colors.grey,
          child: widget.text != null
              ? Container(
                  child: widget.text,
                )
              : widget.image ?? widget.icon,
          //padding: EdgeInsets.all(15.0),
          padding: widget.padding != null ? EdgeInsets.all(widget.padding) : EdgeInsets.all(15.0),
          shape: CircleBorder(
            side: BorderSide(
                width: widget.border != null ? widget.border : 2.0,
                style: BorderStyle.solid,
                color: widget.borderColor ?? Colors.grey),
          ),
        ),
      ),
    );
  }
}

Upvotes: 1

Related Questions