skip to Main Content

In flutter, I have widgets like:

class _MyHomePageState extends State<MyHomePage> {
  @override
  Widget build(BuildContext context) => Scaffold(
        body: OrientationBuilder(
          builder: (context, orientation) {
            const List<ColorfulBox> children = [ColorfulBox(), ColorfulBox()];

            return orientation == Orientation.portrait ? 
                const Row(children: children) : 
                const Column(children: children);            
          },
        ),
      );
}

class ColorfulBox extends StatefulWidget {
  const ColorfulBox({super.key});

  @override
  State<ColorfulBox> createState() => _ColorfulBoxState();
}

class _ColorfulBoxState extends State<ColorfulBox> {
  @override
  Widget build(BuildContext context) => Container(
        width: 100,
        height: 100,
        color: getRandomColor(),
      );
}

Color getRandomColor() {
  var generatedColor = Random().nextInt(Colors.primaries.length);
  return Colors.primaries[generatedColor];
}

Currently when I rotate the device, new state of ColorfulBox will be build what causes color change.

I was wondering how can I keep ColorfulBox state?
I tried adding keys differently named to ColorfulBox and also adding AutomaticKeepAliveClientMixin but none of those two ideas worked.

2

Answers


  1. In fact, your state of widget is not recreated, but the build function is executed again.

    You need call getRandomColor() outside of the build method:
    Use this code:

    class ColorfulBox extends StatefulWidget {
      const ColorfulBox({super.key});
    
      @override
      State<ColorfulBox> createState() => _ColorfulBoxState();
    }
    
    class _ColorfulBoxState extends State<ColorfulBox> {
      final _color=getRandomColor();
      @override
      Widget build(BuildContext context) => Container(
            width: 100,
            height: 100,
            color: _color,
          );
    }
    
    Color getRandomColor() {
      var generatedColor = Random().nextInt(Colors.primaries.length);
      return Colors.primaries[generatedColor];
    }
    
    Login or Signup to reply.
  2. You could set the colors higher up, when you define the children List:

    import 'dart:math';
    
    import 'package:flutter/material.dart';
    
    void main() {
      runApp(const MyApp());
    }
    
    Color _getRandomColor() =>
        Colors.primaries[Random().nextInt(Colors.primaries.length)];
    
    class MyApp extends StatelessWidget {
      const MyApp({super.key});
    
      @override
      Widget build(BuildContext context) => const MaterialApp(home: MyHomePage());
    }
    
    class MyHomePage extends StatelessWidget {
      const MyHomePage({super.key});
    
      @override
      Widget build(BuildContext context) {
        List<ColorfulBox> children = [
          ColorfulBox(key: Key("1"), color: _getRandomColor()),
          ColorfulBox(key: Key("2"), color: _getRandomColor()),
        ];
    
        return Scaffold(body: OrientationBuilder(
          builder: (BuildContext context, Orientation orientation) {
            return orientation == Orientation.portrait
                ? Row(children: children)
                : Column(children: children);
          },
        ));
      }
    }
    
    class ColorfulBox extends StatefulWidget {
      const ColorfulBox({super.key, required this.color});
      final Color color;
      @override
      State<ColorfulBox> createState() => _ColorfulBoxState();
    }
    
    class _ColorfulBoxState extends State<ColorfulBox> {
      @override
      Widget build(BuildContext context) {
        print("build ${widget.key}");
        return Container(
          width: 100,
          height: 100,
          color: widget.color,
        );
      }
    }
    
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search