multi_widget_construction.dart 4.12 KB
Newer Older
1 2 3 4 5 6 7
// Copyright 2014 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

import 'package:flutter/material.dart';

class MultiWidgetConstructTable extends StatefulWidget {
8
  const MultiWidgetConstructTable(this.columnCount, this.rowCount, {Key? key})
9 10
      : super(key: key);

11 12
  final int columnCount;
  final int rowCount;
13 14

  @override
15
  State<MultiWidgetConstructTable> createState() => _MultiWidgetConstructTableState();
16 17 18 19 20 21 22 23 24 25 26
}

class _MultiWidgetConstructTableState extends State<MultiWidgetConstructTable>
    with SingleTickerProviderStateMixin {
  static const List<MaterialColor> colorList = <MaterialColor>[
    Colors.pink, Colors.red, Colors.deepOrange, Colors.orange, Colors.amber,
    Colors.yellow, Colors.lime, Colors.lightGreen, Colors.green, Colors.teal,
    Colors.cyan, Colors.lightBlue, Colors.blue, Colors.indigo, Colors.purple,
  ];
  int counter = 0;

27
  late AnimationController _controller;
28 29 30 31

  @override
  void initState() {
    super.initState();
32 33 34 35 36 37
    _controller = AnimationController(
      vsync: this,
      duration: const Duration(milliseconds: 10000),
      lowerBound: 0,
      upperBound: colorList.length + 1.0,
    )..repeat();
38 39 40 41
  }

  @override
  void dispose() {
42
    _controller.dispose();
43 44 45 46 47
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
48 49 50 51 52 53 54 55
    return AnimatedBuilder(
      animation: _controller,
      builder: (BuildContext context, _) {
        final int totalLength = widget.rowCount * widget.columnCount;
        final int widgetCounter = counter * totalLength;
        final double height = MediaQuery.of(context).size.height / widget.rowCount;
        final double colorPosition = _controller.value;
        final int c1Position = colorPosition.floor();
56 57 58
        final Color c1 = colorList[c1Position % colorList.length][900]!;
        final Color c2 = colorList[(c1Position + 1) % colorList.length][900]!;
        final Color baseColor = Color.lerp(c1, c2, colorPosition - c1Position)!;
59 60 61 62 63 64 65 66 67 68 69 70 71
        counter++;
        return Scaffold(
          body: Table(
            children: List<TableRow>.generate(
              widget.rowCount,
              (int row) => TableRow(
                children: List<Widget>.generate(
                  widget.columnCount,
                  (int column) {
                    final int label = row * widget.columnCount + column;
                    // This implementation rebuild the widget tree for every
                    // frame, and is intentionally designed of poor performance
                    // for benchmark purposes.
72
                    return counter.isEven
73 74 75 76 77 78
                        ? Container(
                            // This key forces rebuilding the element
                            key: ValueKey<int>(widgetCounter + label),
                            color: Color.lerp(
                                Colors.white, baseColor, label / totalLength),
                            constraints: BoxConstraints.expand(height: height),
79
                            child: Text('${widgetCounter + label}'),
80 81 82 83 84
                          )
                        : MyContainer(
                            // This key forces rebuilding the element
                            key: ValueKey<int>(widgetCounter + label),
                            color: Color.lerp(
85
                                Colors.white, baseColor, label / totalLength)!,
86
                            constraints: BoxConstraints.expand(height: height),
87
                            child: Text('${widgetCounter + label}'),
88 89 90 91
                          );
                  },
                ),
              ),
92 93
            ),
          ),
94 95
        );
      },
96 97 98 99 100 101
    );
  }
}

// This class is intended to break the original Widget tree
class MyContainer extends StatelessWidget {
102
  const MyContainer({required this.color, required this.child, required this.constraints, Key? key})
103 104 105 106 107 108 109 110 111 112
      : super(key: key);
  final Color color;
  final Widget child;
  final BoxConstraints constraints;

  @override
  Widget build(BuildContext context) {
    return Container(
      color: color,
      constraints: constraints,
113
      child: child,
114 115 116
    );
  }
}