-
Notifications
You must be signed in to change notification settings - Fork 26.8k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Fix DataCell overflows with column with multiple text widgets, row height doesn't adjust based on content height #70510 #102886
Changes from all commits
77c06b0
966aaf7
49cd421
7c1fd39
d73de8c
c4a86fd
4661315
ada3a90
05bb9c7
8adc783
c98c020
cd1f836
a06aa53
40a08ac
89f858b
7b9f809
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -348,6 +348,7 @@ class DataCell { | |
/// * [DataColumn], which describes a column in the data table. | ||
/// * [DataRow], which contains the data for a row in the data table. | ||
/// * [DataCell], which contains the data for a single cell in the data table. | ||
/// * [DataRowHeightStyle], which contains height settings for data rows. | ||
/// * [PaginatedDataTable], which shows part of the data in a data table and | ||
/// provides controls for paging through the remainder of the data. | ||
/// * <https://material.io/design/components/data-tables.html> | ||
|
@@ -384,7 +385,12 @@ class DataTable extends StatelessWidget { | |
this.onSelectAll, | ||
this.decoration, | ||
this.dataRowColor, | ||
this.dataRowHeight, | ||
@Deprecated( | ||
'Use dataRowHeightStyle instead. ' | ||
'This feature was deprecated after v3.1.0-0.0.pre.', | ||
) | ||
double? dataRowHeight, | ||
DataRowHeightStyle? dataRowHeightStyle, | ||
this.dataTextStyle, | ||
this.headingRowColor, | ||
this.headingRowHeight, | ||
|
@@ -405,7 +411,8 @@ class DataTable extends StatelessWidget { | |
assert(rows != null), | ||
assert(!rows.any((DataRow row) => row.cells.length != columns.length)), | ||
assert(dividerThickness == null || dividerThickness >= 0), | ||
_onlyTextColumn = _initOnlyTextColumn(columns); | ||
_onlyTextColumn = _initOnlyTextColumn(columns), | ||
dataRowHeightStyle = dataRowHeightStyle ?? (dataRowHeight != null ? DataRowHeightStyle.fixed(height: dataRowHeight) : null); | ||
|
||
/// The configuration and labels for the columns in the table. | ||
final List<DataColumn> columns; | ||
|
@@ -489,14 +496,13 @@ class DataTable extends StatelessWidget { | |
/// {@endtemplate} | ||
final MaterialStateProperty<Color?>? dataRowColor; | ||
|
||
/// {@template flutter.material.dataTable.dataRowHeight} | ||
/// The height of each row (excluding the row that contains column headings). | ||
/// {@endtemplate} | ||
/// {@template flutter.material.dataTable.dataRowHeightStyle} | ||
/// The height settings of each row excluding the row that contains column headings. | ||
/// | ||
/// If null, [DataTableThemeData.dataRowHeight] is used. This value defaults | ||
/// to [kMinInteractiveDimension] to adhere to the Material Design | ||
/// specifications. | ||
final double? dataRowHeight; | ||
/// If null, [DataTableThemeData.dataRowHeightStyle] is used. | ||
/// Defaults to [DataRowHeightStyle.fixed] with the height sets to [kMinInteractiveDimension]. | ||
/// {@endtemplate} | ||
final DataRowHeightStyle? dataRowHeightStyle; | ||
|
||
/// {@template flutter.material.dataTable.dataTextStyle} | ||
/// The text style for data rows. | ||
|
@@ -795,6 +801,7 @@ class DataTable extends StatelessWidget { | |
Widget _buildDataCell({ | ||
required BuildContext context, | ||
required EdgeInsetsGeometry padding, | ||
required double? height, | ||
required Widget label, | ||
required bool numeric, | ||
required bool placeholder, | ||
|
@@ -823,13 +830,10 @@ class DataTable extends StatelessWidget { | |
?? dataTableTheme.dataTextStyle | ||
?? themeData.dataTableTheme.dataTextStyle | ||
?? themeData.textTheme.bodyText2!; | ||
final double effectiveDataRowHeight = dataRowHeight | ||
?? dataTableTheme.dataRowHeight | ||
?? themeData.dataTableTheme.dataRowHeight | ||
?? kMinInteractiveDimension; | ||
|
||
label = Container( | ||
padding: padding, | ||
height: effectiveDataRowHeight, | ||
height: height, | ||
alignment: numeric ? Alignment.centerRight : AlignmentDirectional.centerStart, | ||
child: DefaultTextStyle( | ||
style: effectiveDataTextStyle.copyWith( | ||
|
@@ -908,6 +912,13 @@ class DataTable extends StatelessWidget { | |
?? theme.dataTableTheme.columnSpacing | ||
?? _columnSpacing; | ||
|
||
final DataRowHeightStyle effectiveDataRowHeightStyle = dataRowHeightStyle | ||
?? dataTableTheme.dataRowHeightStyle | ||
?? theme.dataTableTheme.dataRowHeightStyle | ||
?? const DataRowHeightStyle.fixed(height: kMinInteractiveDimension); | ||
final double? effectiveDataRowHeight = effectiveDataRowHeightStyle.fixedHeight; | ||
final double effectiveDataRowTopBottomPadding = effectiveDataRowHeightStyle.verticalPadding; | ||
|
||
final List<TableColumnWidth> tableColumns = List<TableColumnWidth>.filled(columns.length + (displayCheckboxColumn ? 1 : 0), const _NullTableColumnWidth()); | ||
final List<TableRow> tableRows = List<TableRow>.generate( | ||
rows.length + 1, // the +1 is for the header row | ||
|
@@ -993,9 +1004,15 @@ class DataTable extends StatelessWidget { | |
paddingEnd = effectiveColumnSpacing / 2.0; | ||
} | ||
|
||
final EdgeInsetsDirectional padding = EdgeInsetsDirectional.only( | ||
final EdgeInsetsDirectional headingPadding = EdgeInsetsDirectional.only( | ||
start: paddingStart, | ||
end: paddingEnd, | ||
); | ||
final EdgeInsetsDirectional cellPadding = EdgeInsetsDirectional.only( | ||
start: paddingStart, | ||
end: paddingEnd, | ||
top: effectiveDataRowTopBottomPadding, | ||
bottom: effectiveDataRowTopBottomPadding, | ||
); | ||
if (dataColumnIndex == _onlyTextColumn) { | ||
tableColumns[displayColumnIndex] = const IntrinsicColumnWidth(flex: 1.0); | ||
|
@@ -1004,7 +1021,7 @@ class DataTable extends StatelessWidget { | |
} | ||
tableRows[0].children![displayColumnIndex] = _buildHeadingCell( | ||
context: context, | ||
padding: padding, | ||
padding: headingPadding, | ||
label: column.label, | ||
tooltip: column.tooltip, | ||
numeric: column.numeric, | ||
|
@@ -1018,7 +1035,8 @@ class DataTable extends StatelessWidget { | |
final DataCell cell = row.cells[dataColumnIndex]; | ||
tableRows[rowIndex].children![displayColumnIndex] = _buildDataCell( | ||
context: context, | ||
padding: padding, | ||
padding: cellPadding, | ||
height: effectiveDataRowHeight, | ||
label: cell.child, | ||
numeric: column.numeric, | ||
placeholder: cell.placeholder, | ||
|
@@ -1043,6 +1061,7 @@ class DataTable extends StatelessWidget { | |
type: MaterialType.transparency, | ||
child: Table( | ||
columnWidths: tableColumns.asMap(), | ||
defaultVerticalAlignment: TableCellVerticalAlignment.middle, | ||
children: tableRows, | ||
border: border, | ||
), | ||
|
@@ -1051,6 +1070,54 @@ class DataTable extends StatelessWidget { | |
} | ||
} | ||
|
||
/// Height settings for DataRows. | ||
/// Either a fixed row height or a row height that adjusts to its content can be specified. | ||
@immutable | ||
class DataRowHeightStyle with Diagnosticable { | ||
/// Creates height settings where all rows are created with the same fixed height. | ||
const DataRowHeightStyle.fixed({ | ||
required double height | ||
}) : fixedHeight = height, verticalPadding = 0.0; | ||
|
||
/// Creates height settings where the row height adjusts to the content. | ||
const DataRowHeightStyle.auto({ | ||
required this.verticalPadding, | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This seems a bit unnecessary. Could the user not just wrap the cell content in Again, this is very expensive because you will need to determine the height of all of the children in the row to determine the ultimate height. I do not know that users will want the trade off in performance in exchange for an auto-size row. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Yes. I like the suggestion.
The first commit used a different approach than the current code, it changed the meaning of the One note about your concerns for changing user facing code. I suppose, for most users there is no depreciation warning because most users use the default height and do not explicitly set dataRowHeight. The users that have set dataRowHeight will get a depreciation warning. However I suppose most apps do not use a lot of DataTable widgets, so there are not many places that need to be adjusted. |
||
}) : fixedHeight = null; | ||
|
||
/// The height of each data row. | ||
/// | ||
/// If set then all rows will get this fixed height, if null then content based height is used. | ||
final double? fixedHeight; | ||
|
||
/// The top and bottom padding of each data row. | ||
/// | ||
/// If fixed height is used then this value is set to 0.0 because the content is vertically centered which makes padding unneeded. | ||
inouiw marked this conversation as resolved.
Show resolved
Hide resolved
inouiw marked this conversation as resolved.
Show resolved
Hide resolved
|
||
final double verticalPadding; | ||
|
||
@override | ||
int get hashCode => Object.hash(fixedHeight, verticalPadding); | ||
|
||
@override | ||
bool operator ==(Object other) { | ||
if (other.runtimeType != runtimeType) { | ||
return false; | ||
} | ||
return other is DataRowHeightStyle | ||
&& other.fixedHeight == fixedHeight | ||
&& other.verticalPadding == verticalPadding; | ||
} | ||
|
||
@override | ||
String toStringShort() => objectRuntimeType(this, 'DataRowHeightStyle'); | ||
|
||
@override | ||
void debugFillProperties(DiagnosticPropertiesBuilder properties) { | ||
super.debugFillProperties(properties); | ||
properties.add(DoubleProperty('fixedHeight', fixedHeight)); | ||
properties.add(DoubleProperty('verticalPadding', verticalPadding)); | ||
} | ||
} | ||
|
||
/// A rectangular area of a Material that responds to touch but clips | ||
/// its ink splashes to the current table row of the nearest table. | ||
/// | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is it reasonable to assume users would want the same for the header row height?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The auto height for the data row is needed if you have some rows that are higher than other rows for example for multiline text. Then you do not want all rows to be e.g. twice as high but only the rows which need it.
For the header row, even though not as convenient as an auto height, it should be enough to be able to set a fixed height.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
How would that logic not apply to the general row height? :)