Search code examples
fluttersetstate

Update variable inside of set state


I'm fairly new to flutter, I have a list of colors and i want to be able to touch a container and switch between the different colors in the list. This would update the color of the container. Also I could have multiple containers in this case 2, so touching one container shouldn't update the other containers.

I had it working using one container, but after creating a method which returns the widget so i could have multiple containers, this does not work.

 import 'package:flutter/material.dart';

class NewGame extends StatefulWidget {
  final Color team1;
  final Color team2;
  final Color team3;

  NewGame(this.team1, this.team2, this.team3);

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

class _NewGameState extends State<NewGame> {
  List<Color> teamColors;
  int team1Index = 0;
  int team2Index = 0;

  @override
  void initState() {
    super.initState();
    teamColors = [widget.team1, widget.team2, widget.team3];
  }

  Widget _buildTeamSelector(int teamIndex) {   
    return GestureDetector(
                onTap: () {
                  setState(() {
                    print('Value of teamColorIndex ${teamIndex.toString()}');
                    if (teamIndex < teamColors.length - 1) {
                      teamIndex++;
                    } else {
                      teamIndex = 0;
                    }
                  });
                },
                child: Container(
                  height: 75,
                  width: 75,
                  decoration: BoxDecoration(
                    color: teamColors[teamIndex],
                    borderRadius: BorderRadius.circular(50),
                  ),
                ),
              );
  }

  @override
  Widget build(BuildContext context) {
    return Card(
      elevation: 5,
      child: Column(
        children: <Widget>[
          Column(
            children: <Widget>[
              Text('Value of team1Index: :$team1Index'),
              Row(
                mainAxisAlignment: MainAxisAlignment.spaceBetween,
                children: <Widget>[
                  Text('Teams:'),
                  _buildTeamSelector(team1Index),
                  _buildTeamSelector(team2Index),
                  Text('Red'),
                ],
              ),
            ],
          ),
        ],
      ),
    );
  }
}

I/flutter (12114): Value of teamColorIndex 0
I/chatty  (12114): uid=10085(com.example.game_tracker) Thread-2 identical 1 line
I/flutter (12114): Value of teamColorIndex 0
I/flutter (12114): Value of teamColorIndex 0
I/chatty  (12114): uid=10085(com.example.game_tracker) Thread-2 identical 4 lines
I/flutter (12114): Value of teamColorIndex 0
I/flutter (12114): Value of teamColorIndex 0

With in the setState the variable doesn't seem to be getting updated. I know this is the issue but i don't know why.


Solution

  • You try to update passed by value argument. Dart don't support passing primitive type by reference, hence you need wrap your primitive value in object like that:

    class Team {
      int index;
    
      Team(this.index);
    }
    
    class NewGame extends StatefulWidget {
      final Color team1;
      final Color team2;
      final Color team3;
    
      NewGame(this.team1, this.team2, this.team3);
    
      @override
      _NewGameState createState() => _NewGameState();
    }
    
    class _NewGameState extends State<NewGame> {
      List<Color> teamColors;
      var team1 = Team(0);
      var team2 = Team(0);
    
      @override
      void initState() {
        super.initState();
        teamColors = [widget.team1, widget.team2, widget.team3];
      }
    
      Widget _buildTeamSelector(Team team) {
        return GestureDetector(
          onTap: () {
            setState(() {
              print('Value of teamColorIndex ${team.index.toString()}');
              if (team.index < teamColors.length - 1) {
                team.index++;
              } else {
                team.index = 0;
              }
            });
          },
          child: Container(
            height: 75,
            width: 75,
            decoration: BoxDecoration(
              color: teamColors[team.index],
              borderRadius: BorderRadius.circular(50),
            ),
          ),
        );
      }
    
      @override
      Widget build(BuildContext context) {
        return Card(
          elevation: 5,
          child: Column(
            children: <Widget>[
              Column(
                children: <Widget>[
                  Text('Value of team1.index: :${team1.index}'),
                  Row(
                    mainAxisAlignment: MainAxisAlignment.spaceBetween,
                    children: <Widget>[
                      Text('Teams:'),
                      _buildTeamSelector(team1),
                      _buildTeamSelector(team2),
                      Text('Red'),
                    ],
                  ),
                ],
              ),
            ],
          ),
        );
      }
    }