Home > Mobile >  Flutter variable changes but it doesn't change on the UI
Flutter variable changes but it doesn't change on the UI

Time:02-23

I have a basic UI like this.

I have a list of containers. When I press the floating button I want to change the color of a random container to a random color. This function picks a random color.

getColor() {
  Random random = Random();
  Color? _color = Color.fromARGB(
      255, random.nextInt(255), random.nextInt(255), random.nextInt(255));
  print("selected color: $_color");
  return _color;
} 

This one is supposed to set the picked color to a random container's color.

void _colorChanger() {
  Random random = Random();
  int i = random.nextInt(4);
  print("selected state : $i");
  if (i == 0) {
    setState(() {
      print("before state 0   $_color0");
      _color0 = getColor();
      print("after state 0   $_color0");
      print("set1");
    });
  } else if (i == 1) {
    setState(() {
      _color1 = getColor();
      print("set2");
    });
  } else if (i == 2) {
    setState(() {
      _color2 = getColor();
      print("set3");
    });
  } else if (i == 3) {
    setState(() {
      _color3 = getColor();
      print("set3");
    });
  }
}

With the prints, I see the change of color's value. But it doesn't change on the UI. How can I fix this?

Here is the source code.

import 'dart:math';

import 'package:flutter/material.dart';

void main() {
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: const MyHomePage(title: 'Flutter Demo Home Page'),
    );
  }
}

class MyHomePage extends StatefulWidget {
  const MyHomePage({Key? key, required this.title}) : super(key: key);

  final String title;

  @override
  State<MyHomePage> createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  @override
  Widget build(BuildContext context) {
    getColor() {
      Random random = Random();
      Color? _color = Color.fromARGB(
          255, random.nextInt(255), random.nextInt(255), random.nextInt(255));
      print("selected color: $_color");
      return _color;
    }

    Color? _color0 = Colors.yellow;
    Color? _color1 = Colors.white;
    Color? _color2 = Colors.red;
    Color? _color3 = Colors.blue;

    void _colorChanger() {
      Random random = Random();
      int i = random.nextInt(4);
      print("selected state : $i");
      if (i == 0) {
        setState(() {
          print("before state 0   $_color0");
          _color0 = getColor();
          print("after state 0   $_color0");
          print("set1");
        });
      } else if (i == 1) {
        setState(() {
          _color1 = getColor();
          print("set2");
        });
      } else if (i == 2) {
        setState(() {
          _color2 = getColor();
          print("set3");
        });
      } else if (i == 3) {
        setState(() {
          _color3 = getColor();
          print("set3");
        });
      }
    }

    var listofContainers = [
      Container(
        color: _color0,
        width: 50,
        height: 50,
        child: const Center(child: Text('Container 1')),
      ),
      Container(
        color: _color1,
        child: const Center(child: Text('Container 2')),
      ),
      Container(
        color: _color2,
        width: 50,
        height: 50,
        child: const Center(child: Text('Container 3')),
      ),
      Container(
        color: _color3,
        width: 50,
        height: 50,
        child: const Center(child: Text('Container 4')),
      )
    ];

    return Scaffold(
      appBar: AppBar(
        title: Text(widget.title),
      ),
      body: Center(
        child: GridView.count(
          crossAxisCount: 2,
          children: [
            listofContainers[0],
            listofContainers[1],
            listofContainers[2],
            listofContainers[3],
            FloatingActionButton(
              onPressed: () {
                _colorChanger();
              },
              child: Text("Change Color"),
            ),
          ],
        ),
      ),
    );
  }
}

CodePudding user response:

Your colors are being overriden on every widget rebuild (when you call setState because the values are inside of the same build method. Take both the Color values and the getColor method (also the colorChanger method) outside of the build method and run it, you'll see it work, as in:


class _MyHomePageState extends State<MyHomePage> {
  
  getColor() {
      Random random = Random();
      Color? _color = Color.fromARGB(
          255, random.nextInt(255), random.nextInt(255), random.nextInt(255));
      print("selected color: $_color");
      return _color;
    }

    Color? _color0 = Colors.yellow;
    Color? _color1 = Colors.white;
    Color? _color2 = Colors.red;
    Color? _color3 = Colors.blue;

  void _colorChanger() { ... }
  
  @override
  Widget build(BuildContext context) {
    // rest of the code
  }
}
  • Related