TSR
TSR

Reputation: 20496

setState does not update wiget UI

I spent few hours trying to understand why clicking on the IconButton does not toggle change its icon.

import 'package:flutter/material.dart';
import 'dart:core';
class TestIconChange extends StatefulWidget {
  @override
  _TestIconChangeState createState() => _TestIconChangeState();
}

class _TestIconChangeState extends State<TestIconChange>
    with TickerProviderStateMixin {
  IconData _iconData = Icons.add;
  AnimationController _animationController1;

  Widget _child;

  @override
  void initState() {
    super.initState();
    _animationController1 = AnimationController(
      vsync: this,
      value: 1,
      duration: Duration(seconds: 1),
    );
  }

  @override
  Widget build(BuildContext context) {
    if (_child == null) _child = _buildButton();
    return Scaffold(
      body: Container(
        child: Center(
          child: Column(
            mainAxisAlignment: MainAxisAlignment.spaceEvenly,
            children: <Widget>[
              AnimatedSwitcher(
                duration: Duration(milliseconds: 100),
                child: _child,
              ),
              RaisedButton(
                child: Text('Text Child'),
                onPressed: (() {
                  setState(() {
                    _child = Text('Dummy text');
                  });
                }),
              ),
              RaisedButton(
                child: Text('Button Child'),
                onPressed: (() {
                  setState(() {
                    _child =_buildButton();
                  },);
                }),
              )
            ],
          ),
        ),
      ),
    );
  }

  Widget _buildButton() {
    return      IconButton(
      onPressed: () {
        setState(() {
          (_iconData == Icons.add)
              ? _iconData = Icons.remove
              : _iconData = Icons.add;
        });
      },
      icon: Icon(_iconData),
    );

  }
}

Upvotes: 0

Views: 561

Answers (1)

Maxim Milyutin
Maxim Milyutin

Reputation: 616

When you call setState it rebuild only Widgets that build in build method.

The main problem was that you didn't do it. You didn't rebuild _child in build method.

This line in your code wrong: if (_child == null) _child = _buildButton();

If you make it like this _child = _buildButton(); then work only button +/-, but not works change to text. Need refactoring of your code!

So, I made refactoring of your code and add ChildType that indicate what type of Widget you want to show: text or button. And then use it in setState method. Now it works, as you expected :)

import 'package:flutter/material.dart';
import 'dart:core';
class TestIconChange extends StatefulWidget {
  @override
  _TestIconChangeState createState() => _TestIconChangeState();
}

enum ChildType {text, button}

class _TestIconChangeState extends State<TestIconChange>
    with TickerProviderStateMixin {

  ChildType curChildType = ChildType.button;
  IconData _iconData = Icons.add;

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Container(
        alignment: Alignment.center,

          child: Column(
            mainAxisAlignment: MainAxisAlignment.spaceEvenly,
            children: <Widget>[
              AnimatedSwitcher(
                duration: Duration(milliseconds: 100),
                child: _buildButton(),
              ),
              RaisedButton(
                child: Text('Text Child'),
                onPressed: (() {
                  setState(() {
                    curChildType = ChildType.text;
                  });
                }),
              ),
              RaisedButton(
                child: Text('Button Child'),
                onPressed: (() {
                  setState(() {
                    curChildType = ChildType.button;
                  },);
                }),
              )
            ],
          ),
      ),
    );
  }

  Widget _buildButton() {
    if (curChildType == ChildType.text) {
      return Text('Dummy text');
    }
    else {
      return IconButton(
        icon: Icon(_iconData),
        onPressed: () {
          setState(() {
            _iconData = (_iconData == Icons.add) ? Icons.remove : _iconData = Icons.add;
          });
        },
      );
    }
  }
}

Good Luck!

Upvotes: 2

Related Questions