From ad507723ec65f7b0e67d587475eff3829bc91cf8 Mon Sep 17 00:00:00 2001 From: chunhtai <47866232+chunhtai@users.noreply.github.com> Date: Wed, 12 Jun 2019 16:58:24 -0700 Subject: [PATCH] fix Applying decoration for a table row widget will cause render exception (#34285) --- packages/flutter/lib/src/rendering/table.dart | 5 ++- packages/flutter/test/widgets/table_test.dart | 36 +++++++++++++++++++ 2 files changed, 40 insertions(+), 1 deletion(-) diff --git a/packages/flutter/lib/src/rendering/table.dart b/packages/flutter/lib/src/rendering/table.dart index ec9ebef935..926dc60902 100644 --- a/packages/flutter/lib/src/rendering/table.dart +++ b/packages/flutter/lib/src/rendering/table.dart @@ -518,6 +518,8 @@ class RenderTable extends RenderBox { /// the table, unlike decorations for individual cells, which might not fill /// either. List get rowDecorations => List.unmodifiable(_rowDecorations ?? const []); + // _rowDecorations and _rowDecorationPainters need to be in sync. They have to + // either both be null or have same length. List _rowDecorations; List _rowDecorationPainters; set rowDecorations(List value) { @@ -703,7 +705,7 @@ class RenderTable extends RenderBox { if (_rowDecorationPainters != null) { for (BoxPainter painter in _rowDecorationPainters) painter?.dispose(); - _rowDecorationPainters = null; + _rowDecorationPainters = List(_rowDecorations.length); } for (RenderBox child in _children) child?.detach(); @@ -1137,6 +1139,7 @@ class RenderTable extends RenderBox { } assert(_rowTops.length == rows + 1); if (_rowDecorations != null) { + assert(_rowDecorations.length == _rowDecorationPainters.length); final Canvas canvas = context.canvas; for (int y = 0; y < rows; y += 1) { if (_rowDecorations.length <= y) diff --git a/packages/flutter/test/widgets/table_test.dart b/packages/flutter/test/widgets/table_test.dart index 3df1c86906..e96c1ada90 100644 --- a/packages/flutter/test/widgets/table_test.dart +++ b/packages/flutter/test/widgets/table_test.dart @@ -5,6 +5,7 @@ import 'package:flutter_test/flutter_test.dart'; import 'package:flutter/rendering.dart'; import 'package:flutter/widgets.dart'; +import 'package:flutter/material.dart'; class TestStatefulWidget extends StatefulWidget { const TestStatefulWidget({ Key key }) : super(key: key); @@ -67,6 +68,41 @@ void main() { await run(TextDirection.rtl); }); + testWidgets('Table widget can be detached and re-attached', (WidgetTester tester) async { + final Widget table = Table( + key: GlobalKey(), + children: const [ + TableRow( + decoration: BoxDecoration( + color: Colors.yellow + ), + children: [Placeholder()], + ), + ], + ); + await tester.pumpWidget( + Directionality( + textDirection: TextDirection.ltr, + child: Center( + child: table, + ), + ), + ); + // Move table to a different location to simulate detaching and re-attaching effect. + await tester.pumpWidget( + Directionality( + textDirection: TextDirection.ltr, + child: Center( + child: Center( + child: table + ), + ), + ), + ); + + expect(tester.takeException(), isNull); + }); + testWidgets('Table widget - column offset (LTR)', (WidgetTester tester) async { await tester.pumpWidget( Directionality(