| // 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.of(context).size.height / 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, |
| ); |
| } |
| } |