Unverified Commit 71254a61 authored by Shi-Hao Hong's avatar Shi-Hao Hong Committed by GitHub

Custom height parameters for DataTable header and data rows (#33535)

* Custom dataRowHeight for DataTable and PaginatedDataTable

* Custom headingRowHeight for DataTable and PaginatedDataTable
parent 23c25d9e
......@@ -262,6 +262,8 @@ class DataTable extends StatelessWidget {
this.sortColumnIndex,
this.sortAscending = true,
this.onSelectAll,
this.dataRowHeight = 48.0,
this.headingRowHeight = 56.0,
this.horizontalMargin = 24.0,
this.columnSpacing = 56.0,
@required this.rows,
......@@ -269,6 +271,8 @@ class DataTable extends StatelessWidget {
assert(columns.isNotEmpty),
assert(sortColumnIndex == null || (sortColumnIndex >= 0 && sortColumnIndex < columns.length)),
assert(sortAscending != null),
assert(dataRowHeight != null),
assert(headingRowHeight != null),
assert(horizontalMargin != null),
assert(columnSpacing != null),
assert(rows != null),
......@@ -315,6 +319,16 @@ class DataTable extends StatelessWidget {
/// row is selectable.
final ValueSetter<bool> onSelectAll;
/// The height of each row (excluding the row that contains column headings).
///
/// This value defaults to 48.0 to adhere to the Material Design specifications.
final double dataRowHeight;
/// The height of the heading row.
///
/// This value defaults to 56.0 to adhere to the Material Design specifications.
final double headingRowHeight;
/// The horizontal margin between the edges of the table and the content
/// in the first and last cells of each row.
///
......@@ -330,7 +344,9 @@ class DataTable extends StatelessWidget {
final double columnSpacing;
/// The data to show in each row (excluding the row that contains
/// the column headings). Must be non-null, but may be empty.
/// the column headings).
///
/// Must be non-null, but may be empty.
final List<DataRow> rows;
// Set by the constructor to the index of the only Column that is
......@@ -367,8 +383,6 @@ class DataTable extends StatelessWidget {
}
}
static const double _headingRowHeight = 56.0;
static const double _dataRowHeight = 48.0;
static const double _sortArrowPadding = 2.0;
static const double _headingFontSize = 12.0;
static const Duration _sortArrowAnimationDuration = Duration(milliseconds: 150);
......@@ -430,14 +444,14 @@ class DataTable extends StatelessWidget {
}
label = Container(
padding: padding,
height: _headingRowHeight,
height: headingRowHeight,
alignment: numeric ? Alignment.centerRight : AlignmentDirectional.centerStart,
child: AnimatedDefaultTextStyle(
style: TextStyle(
// TODO(ianh): font family should match Theme; see https://github.com/flutter/flutter/issues/3116
fontWeight: FontWeight.w500,
fontSize: _headingFontSize,
height: math.min(1.0, _headingRowHeight / _headingFontSize),
height: math.min(1.0, headingRowHeight / _headingFontSize),
color: (Theme.of(context).brightness == Brightness.light)
? ((onSort != null && sorted) ? Colors.black87 : Colors.black54)
: ((onSort != null && sorted) ? Colors.white : Colors.white70),
......@@ -483,7 +497,7 @@ class DataTable extends StatelessWidget {
}
label = Container(
padding: padding,
height: _dataRowHeight,
height: dataRowHeight,
alignment: numeric ? Alignment.centerRight : AlignmentDirectional.centerStart,
child: DefaultTextStyle(
style: TextStyle(
......
......@@ -70,6 +70,8 @@ class PaginatedDataTable extends StatefulWidget {
this.sortColumnIndex,
this.sortAscending = true,
this.onSelectAll,
this.dataRowHeight = 48.0,
this.headingRowHeight = 56.0,
this.horizontalMargin = 24.0,
this.columnSpacing = 56.0,
this.initialFirstRowIndex = 0,
......@@ -85,6 +87,8 @@ class PaginatedDataTable extends StatefulWidget {
assert(columns.isNotEmpty),
assert(sortColumnIndex == null || (sortColumnIndex >= 0 && sortColumnIndex < columns.length)),
assert(sortAscending != null),
assert(dataRowHeight != null),
assert(headingRowHeight != null),
assert(horizontalMargin != null),
assert(columnSpacing != null),
assert(rowsPerPage != null),
......@@ -135,6 +139,16 @@ class PaginatedDataTable extends StatefulWidget {
/// See [DataTable.onSelectAll].
final ValueSetter<bool> onSelectAll;
/// The height of each row (excluding the row that contains column headings).
///
/// This value is optional and defaults to 48.0 if not specified.
final double dataRowHeight;
/// The height of the heading row.
///
/// This value is optional and defaults to 56.0 if not specified.
final double headingRowHeight;
/// The horizontal margin between the edges of the table and the content
/// in the first and last cells of each row.
///
......@@ -448,6 +462,8 @@ class PaginatedDataTableState extends State<PaginatedDataTable> {
sortColumnIndex: widget.sortColumnIndex,
sortAscending: widget.sortAscending,
onSelectAll: widget.onSelectAll,
dataRowHeight: widget.dataRowHeight,
headingRowHeight: widget.headingRowHeight,
horizontalMargin: widget.horizontalMargin,
columnSpacing: widget.columnSpacing,
rows: _getRows(_firstRowIndex, widget.rowsPerPage),
......
......@@ -267,6 +267,123 @@ void main() {
expect(tester.takeException(), isNull);
});
testWidgets('DataTable custom row height', (WidgetTester tester) async {
Widget buildCustomTable({
int sortColumnIndex,
bool sortAscending = true,
double dataRowHeight = 48.0,
double headingRowHeight = 56.0,
}) {
return DataTable(
sortColumnIndex: sortColumnIndex,
sortAscending: sortAscending,
onSelectAll: (bool value) {},
dataRowHeight: dataRowHeight,
headingRowHeight: headingRowHeight,
columns: <DataColumn>[
const DataColumn(
label: Text('Name'),
tooltip: 'Name',
),
DataColumn(
label: const Text('Calories'),
tooltip: 'Calories',
numeric: true,
onSort: (int columnIndex, bool ascending) {},
),
],
rows: kDesserts.map<DataRow>((Dessert dessert) {
return DataRow(
key: Key(dessert.name),
onSelectChanged: (bool selected) {},
cells: <DataCell>[
DataCell(
Text(dessert.name),
),
DataCell(
Text('${dessert.calories}'),
showEditIcon: true,
onTap: () {},
),
],
);
}).toList(),
);
}
// DEFAULT VALUES
await tester.pumpWidget(MaterialApp(
home: Material(
child: DataTable(
onSelectAll: (bool value) {},
columns: <DataColumn>[
const DataColumn(
label: Text('Name'),
tooltip: 'Name',
),
DataColumn(
label: const Text('Calories'),
tooltip: 'Calories',
numeric: true,
onSort: (int columnIndex, bool ascending) {},
),
],
rows: kDesserts.map<DataRow>((Dessert dessert) {
return DataRow(
key: Key(dessert.name),
onSelectChanged: (bool selected) {},
cells: <DataCell>[
DataCell(
Text(dessert.name),
),
DataCell(
Text('${dessert.calories}'),
showEditIcon: true,
onTap: () {},
),
],
);
}).toList(),
),
),
));
expect(tester.renderObject<RenderBox>(
find.widgetWithText(Container, 'Name')
).size.height, 56.0); // This is the header row height
expect(tester.renderObject<RenderBox>(
find.widgetWithText(Container, 'Frozen yogurt')
).size.height, 48.0); // This is the data row height
// CUSTOM VALUES
await tester.pumpWidget(MaterialApp(
home: Material(child: buildCustomTable(headingRowHeight: 48.0)),
));
expect(tester.renderObject<RenderBox>(
find.widgetWithText(Container, 'Name')
).size.height, 48.0);
await tester.pumpWidget(MaterialApp(
home: Material(child: buildCustomTable(headingRowHeight: 64.0)),
));
expect(tester.renderObject<RenderBox>(
find.widgetWithText(Container, 'Name')
).size.height, 64.0);
await tester.pumpWidget(MaterialApp(
home: Material(child: buildCustomTable(dataRowHeight: 30.0)),
));
expect(tester.renderObject<RenderBox>(
find.widgetWithText(Container, 'Frozen yogurt')
).size.height, 30.0);
await tester.pumpWidget(MaterialApp(
home: Material(child: buildCustomTable(dataRowHeight: 56.0)),
));
expect(tester.renderObject<RenderBox>(
find.widgetWithText(Container, 'Frozen yogurt')
).size.height, 56.0);
});
testWidgets('DataTable custom horizontal padding - checkbox', (WidgetTester tester) async {
const double _defaultHorizontalMargin = 24.0;
const double _defaultColumnSpacing = 56.0;
......
......@@ -296,6 +296,86 @@ void main() {
expect(find.text('Rows per page:'), findsOneWidget);
expect(tester.getTopLeft(find.text('Rows per page:')).dx, 18.0); // 14 padding in the footer row, 4 padding from the card
});
testWidgets('PaginatedDataTable custom row height', (WidgetTester tester) async {
final TestDataSource source = TestDataSource();
Widget buildCustomHeightPaginatedTable({
double dataRowHeight = 48.0,
double headingRowHeight = 56.0,
}) {
return PaginatedDataTable(
header: const Text('Test table'),
source: source,
rowsPerPage: 2,
availableRowsPerPage: const <int>[
2, 4, 8, 16,
],
onRowsPerPageChanged: (int rowsPerPage) {},
onPageChanged: (int rowIndex) {},
columns: const <DataColumn>[
DataColumn(label: Text('Name')),
DataColumn(label: Text('Calories'), numeric: true),
DataColumn(label: Text('Generation')),
],
dataRowHeight: dataRowHeight,
headingRowHeight: headingRowHeight,
);
}
// DEFAULT VALUES
await tester.pumpWidget(MaterialApp(
home: PaginatedDataTable(
header: const Text('Test table'),
source: source,
rowsPerPage: 2,
availableRowsPerPage: const <int>[
2, 4, 8, 16,
],
onRowsPerPageChanged: (int rowsPerPage) {},
onPageChanged: (int rowIndex) {},
columns: const <DataColumn>[
DataColumn(label: Text('Name')),
DataColumn(label: Text('Calories'), numeric: true),
DataColumn(label: Text('Generation')),
],
),
));
expect(tester.renderObject<RenderBox>(
find.widgetWithText(Container, 'Name').first
).size.height, 56.0); // This is the header row height
expect(tester.renderObject<RenderBox>(
find.widgetWithText(Container, 'Frozen yogurt (0)').first
).size.height, 48.0); // This is the data row height
// CUSTOM VALUES
await tester.pumpWidget(MaterialApp(
home: Material(child: buildCustomHeightPaginatedTable(headingRowHeight: 48.0)),
));
expect(tester.renderObject<RenderBox>(
find.widgetWithText(Container, 'Name').first
).size.height, 48.0);
await tester.pumpWidget(MaterialApp(
home: Material(child: buildCustomHeightPaginatedTable(headingRowHeight: 64.0)),
));
expect(tester.renderObject<RenderBox>(
find.widgetWithText(Container, 'Name').first
).size.height, 64.0);
await tester.pumpWidget(MaterialApp(
home: Material(child: buildCustomHeightPaginatedTable(dataRowHeight: 30.0)),
));
expect(tester.renderObject<RenderBox>(
find.widgetWithText(Container, 'Frozen yogurt (0)').first
).size.height, 30.0);
await tester.pumpWidget(MaterialApp(
home: Material(child: buildCustomHeightPaginatedTable(dataRowHeight: 56.0)),
));
expect(tester.renderObject<RenderBox>(
find.widgetWithText(Container, 'Frozen yogurt (0)').first
).size.height, 56.0);
});
testWidgets('PaginatedDataTable custom horizontal padding - checkbox', (WidgetTester tester) async {
const double _defaultHorizontalMargin = 24.0;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment