mirror of
https://github.com/flutter/flutter.git
synced 2026-02-20 02:29:02 +08:00
Fix a DataTable crash and improve some docs (#100959)
This commit is contained in:
parent
fd360c4a1d
commit
ef5a6da35a
@ -33,21 +33,27 @@ class MyStatelessWidget extends StatelessWidget {
|
||||
return DataTable(
|
||||
columns: const <DataColumn>[
|
||||
DataColumn(
|
||||
label: Text(
|
||||
'Name',
|
||||
style: TextStyle(fontStyle: FontStyle.italic),
|
||||
label: Expanded(
|
||||
child: Text(
|
||||
'Name',
|
||||
style: TextStyle(fontStyle: FontStyle.italic),
|
||||
),
|
||||
),
|
||||
),
|
||||
DataColumn(
|
||||
label: Text(
|
||||
'Age',
|
||||
style: TextStyle(fontStyle: FontStyle.italic),
|
||||
label: Expanded(
|
||||
child: Text(
|
||||
'Age',
|
||||
style: TextStyle(fontStyle: FontStyle.italic),
|
||||
),
|
||||
),
|
||||
),
|
||||
DataColumn(
|
||||
label: Text(
|
||||
'Role',
|
||||
style: TextStyle(fontStyle: FontStyle.italic),
|
||||
label: Expanded(
|
||||
child: Text(
|
||||
'Role',
|
||||
style: TextStyle(fontStyle: FontStyle.italic),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
|
||||
@ -47,9 +47,14 @@ class DataColumn {
|
||||
/// [Icon] (typically using size 18), or a [Row] with an icon and
|
||||
/// some text.
|
||||
///
|
||||
/// By default, this widget will only occupy the minimal space. If you want
|
||||
/// it to take the entire remaining space, e.g. when you want to use [Center],
|
||||
/// you can wrap it with an [Expanded].
|
||||
/// The [label] is placed within a [Row] along with the
|
||||
/// sort indicator (if applicable). By default, [label] only occupy minimal
|
||||
/// space. It is recommended to place the label content in an [Expanded] or
|
||||
/// [Flexible] as [label] to control how the content flexes. Otherwise,
|
||||
/// an exception will occur when the available space is insufficient.
|
||||
///
|
||||
/// By default, [DefaultTextStyle.softWrap] of this subtree will be set to false.
|
||||
/// Use [DefaultTextStyle.merge] to override it if needed.
|
||||
///
|
||||
/// The label should not include the sort indicator.
|
||||
final Widget label;
|
||||
|
||||
@ -988,6 +988,7 @@ class RenderTable extends RenderBox {
|
||||
// cache the table geometry for painting purposes
|
||||
final List<double> _rowTops = <double>[];
|
||||
Iterable<double>? _columnLefts;
|
||||
late double _tableWidth;
|
||||
|
||||
/// Returns the position and dimensions of the box that the given
|
||||
/// row covers, in this render object's coordinate space (so the
|
||||
@ -1050,26 +1051,26 @@ class RenderTable extends RenderBox {
|
||||
if (rows * columns == 0) {
|
||||
// TODO(ianh): if columns is zero, this should be zero width
|
||||
// TODO(ianh): if columns is not zero, this should be based on the column width specifications
|
||||
_tableWidth = 0.0;
|
||||
size = constraints.constrain(Size.zero);
|
||||
return;
|
||||
}
|
||||
final List<double> widths = _computeColumnWidths(constraints);
|
||||
final List<double> positions = List<double>.filled(columns, 0.0);
|
||||
final double tableWidth;
|
||||
switch (textDirection) {
|
||||
case TextDirection.rtl:
|
||||
positions[columns - 1] = 0.0;
|
||||
for (int x = columns - 2; x >= 0; x -= 1)
|
||||
positions[x] = positions[x+1] + widths[x+1];
|
||||
_columnLefts = positions.reversed;
|
||||
tableWidth = positions.first + widths.first;
|
||||
_tableWidth = positions.first + widths.first;
|
||||
break;
|
||||
case TextDirection.ltr:
|
||||
positions[0] = 0.0;
|
||||
for (int x = 1; x < columns; x += 1)
|
||||
positions[x] = positions[x-1] + widths[x-1];
|
||||
_columnLefts = positions;
|
||||
tableWidth = positions.last + widths.last;
|
||||
_tableWidth = positions.last + widths.last;
|
||||
break;
|
||||
}
|
||||
_rowTops.clear();
|
||||
@ -1150,7 +1151,7 @@ class RenderTable extends RenderBox {
|
||||
rowTop += rowHeight;
|
||||
}
|
||||
_rowTops.add(rowTop);
|
||||
size = constraints.constrain(Size(tableWidth, rowTop));
|
||||
size = constraints.constrain(Size(_tableWidth, rowTop));
|
||||
assert(_rowTops.length == rows + 1);
|
||||
}
|
||||
|
||||
@ -1181,7 +1182,7 @@ class RenderTable extends RenderBox {
|
||||
assert(_children.length == rows * columns);
|
||||
if (rows * columns == 0) {
|
||||
if (border != null) {
|
||||
final Rect borderRect = Rect.fromLTWH(offset.dx, offset.dy, size.width, 0.0);
|
||||
final Rect borderRect = Rect.fromLTWH(offset.dx, offset.dy, _tableWidth, 0.0);
|
||||
border!.paint(context.canvas, borderRect, rows: const <double>[], columns: const <double>[]);
|
||||
}
|
||||
return;
|
||||
@ -1216,7 +1217,7 @@ class RenderTable extends RenderBox {
|
||||
// The border rect might not fill the entire height of this render object
|
||||
// if the rows underflow. We always force the columns to fill the width of
|
||||
// the render object, which means the columns cannot underflow.
|
||||
final Rect borderRect = Rect.fromLTWH(offset.dx, offset.dy, size.width, _rowTops.last);
|
||||
final Rect borderRect = Rect.fromLTWH(offset.dx, offset.dy, _tableWidth, _rowTops.last);
|
||||
final Iterable<double> rows = _rowTops.getRange(1, _rowTops.length - 1);
|
||||
final Iterable<double> columns = _columnLefts!.skip(1);
|
||||
border!.paint(context.canvas, borderRect, rows: rows, columns: columns);
|
||||
|
||||
@ -1855,4 +1855,42 @@ void main() {
|
||||
expect(tableBorder?.bottom.width, null);
|
||||
expect(tableBorder?.top.color, null);
|
||||
});
|
||||
|
||||
// Regression test for https://github.com/flutter/flutter/issues/100952
|
||||
testWidgets('Do not crashes when paint borders in a narrow space', (WidgetTester tester) async {
|
||||
const List<DataColumn> columns = <DataColumn>[
|
||||
DataColumn(label: Text('column1')),
|
||||
DataColumn(label: Text('column2')),
|
||||
];
|
||||
|
||||
const List<DataCell> cells = <DataCell>[
|
||||
DataCell(Text('cell1')),
|
||||
DataCell(Text('cell2')),
|
||||
];
|
||||
|
||||
const List<DataRow> rows = <DataRow>[
|
||||
DataRow(cells: cells),
|
||||
DataRow(cells: cells),
|
||||
];
|
||||
|
||||
await tester.pumpWidget(
|
||||
MaterialApp(
|
||||
home: Material(
|
||||
child: Center(
|
||||
child: SizedBox(
|
||||
width: 117.0,
|
||||
child: DataTable(
|
||||
border: TableBorder.all(width: 2, color: Colors.red),
|
||||
columns: columns,
|
||||
rows: rows,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
// Go without crashes.
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user