| // 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 { | |
| const MultiWidgetConstructTable(this.columnCount, this.rowCount, {super.key}); | |
| final int columnCount; | |
| final int rowCount; | |
| @override | |
| State<MultiWidgetConstructTable> createState() => _MultiWidgetConstructTableState(); | |
| } | |
| 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; | |
| late AnimationController _controller; | |
| @override | |
| void initState() { | |
| super.initState(); | |
| _controller = AnimationController( | |
| vsync: this, | |
| duration: const Duration(milliseconds: 10000), | |
| upperBound: colorList.length + 1.0, | |
| )..repeat(); | |
| } | |
| @override | |
| void dispose() { | |
| _controller.dispose(); | |
| super.dispose(); | |
| } | |
| @override | |
| Widget build(BuildContext context) { | |
| return AnimatedBuilder( | |
| animation: _controller, | |
| builder: (BuildContext context, _) { | |
| final int totalLength = widget.rowCount * widget.columnCount; | |
| final int widgetCounter = counter * totalLength; | |
| final double height = MediaQuery.heightOf(context) / widget.rowCount; | |
| final double colorPosition = _controller.value; | |
| final int c1Position = colorPosition.floor(); | |
| 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)!; | |
| 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. | |
| return counter.isEven | |
| ? 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), | |
| child: Text('${widgetCounter + label}'), | |
| ) | |
| : MyContainer( | |
| // This key forces rebuilding the element | |
| key: ValueKey<int>(widgetCounter + label), | |
| color: Color.lerp(Colors.white, baseColor, label / totalLength)!, | |
| constraints: BoxConstraints.expand(height: height), | |
| child: Text('${widgetCounter + label}'), | |
| ); | |
| }), | |
| ), | |
| ), | |
| ), | |
| ); | |
| }, | |
| ); | |
| } | |
| } | |
| // This class is intended to break the original Widget tree | |
| class MyContainer extends StatelessWidget { | |
| const MyContainer({ | |
| required this.color, | |
| required this.child, | |
| required this.constraints, | |
| super.key, | |
| }); | |
| final Color color; | |
| final Widget child; | |
| final BoxConstraints constraints; | |
| @override | |
| Widget build(BuildContext context) { | |
| return Container(color: color, constraints: constraints, child: child); | |
| } | |
| } |