mirror of
https://github.com/flutter/flutter.git
synced 2026-02-20 02:29:02 +08:00
This reverts commit cb4b8677219482e3378b1b6bfeff1241a453ccb6.
This commit is contained in:
parent
e10bdbbd9d
commit
0bb1e573fc
@ -52,7 +52,6 @@ export 'src/material/constants.dart';
|
||||
export 'src/material/curves.dart';
|
||||
export 'src/material/data_table.dart';
|
||||
export 'src/material/data_table_source.dart';
|
||||
export 'src/material/data_table_theme.dart';
|
||||
export 'src/material/debug.dart';
|
||||
export 'src/material/dialog.dart';
|
||||
export 'src/material/dialog_theme.dart';
|
||||
|
||||
@ -11,12 +11,12 @@ import 'package:flutter/rendering.dart';
|
||||
import 'package:flutter/widgets.dart';
|
||||
|
||||
import 'checkbox.dart';
|
||||
import 'colors.dart';
|
||||
import 'constants.dart';
|
||||
import 'debug.dart';
|
||||
import 'divider.dart';
|
||||
import 'dropdown.dart';
|
||||
import 'icons.dart';
|
||||
import 'ink_decoration.dart';
|
||||
import 'ink_well.dart';
|
||||
import 'material.dart';
|
||||
import 'material_state.dart';
|
||||
@ -414,27 +414,25 @@ class DataTable extends StatelessWidget {
|
||||
this.sortColumnIndex,
|
||||
this.sortAscending = true,
|
||||
this.onSelectAll,
|
||||
this.decoration,
|
||||
this.dataRowColor,
|
||||
this.dataRowHeight,
|
||||
this.dataTextStyle,
|
||||
this.headingRowColor,
|
||||
this.headingRowHeight,
|
||||
this.headingTextStyle,
|
||||
this.horizontalMargin,
|
||||
this.columnSpacing,
|
||||
this.dataRowHeight = kMinInteractiveDimension,
|
||||
this.headingRowHeight = 56.0,
|
||||
this.horizontalMargin = 24.0,
|
||||
this.columnSpacing = 56.0,
|
||||
this.showCheckboxColumn = true,
|
||||
this.showBottomBorder = false,
|
||||
this.dividerThickness,
|
||||
this.dividerThickness = 1.0,
|
||||
@required this.rows,
|
||||
}) : assert(columns != null),
|
||||
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(showCheckboxColumn != null),
|
||||
assert(rows != null),
|
||||
assert(!rows.any((DataRow row) => row.cells.length != columns.length)),
|
||||
assert(dividerThickness == null || dividerThickness >= 0),
|
||||
assert(dividerThickness != null && dividerThickness >= 0),
|
||||
_onlyTextColumn = _initOnlyTextColumn(columns),
|
||||
super(key: key);
|
||||
|
||||
@ -477,117 +475,27 @@ class DataTable extends StatelessWidget {
|
||||
/// row is selectable.
|
||||
final ValueSetter<bool> onSelectAll;
|
||||
|
||||
/// {@template flutter.material.dataTable.decoration}
|
||||
/// The background and border decoration for the table.
|
||||
/// {@endtemplate}
|
||||
///
|
||||
/// By default there is no decoration.
|
||||
final BoxDecoration decoration;
|
||||
|
||||
/// {@template flutter.material.dataTable.dataRowColor}
|
||||
/// The background color for the data rows.
|
||||
///
|
||||
/// The effective background color can be made to depend on the
|
||||
/// [MaterialState] state, i.e. if the row is selected, pressed, hovered,
|
||||
/// focused, disabled or enabled. The color is painted as an overlay to the
|
||||
/// row. To make sure that the row's [InkWell] is visible (when pressed,
|
||||
/// hovered and focused), it is recommended to use a translucent background
|
||||
/// color.
|
||||
/// {@endtemplate}
|
||||
///
|
||||
/// By default, the background color is transparent unless selected. Selected
|
||||
/// rows have a grey translucent color. To set a different color for
|
||||
/// individual rows, see [DataRow.color].
|
||||
///
|
||||
/// {@template flutter.material.dataTable.dataRowColorCode}
|
||||
/// ```dart
|
||||
/// DataTable(
|
||||
/// dataRowColor: MaterialStateProperty.resolveWith<Color>((Set<MaterialState> states) {
|
||||
/// if (states.contains(MaterialState.selected))
|
||||
/// return Theme.of(context).colorScheme.primary.withOpacity(0.08);
|
||||
/// return null; // Use the default value.
|
||||
/// }),
|
||||
/// )
|
||||
/// ```
|
||||
///
|
||||
/// See also:
|
||||
///
|
||||
/// * The Material Design specification for overlay colors and how they
|
||||
/// match a component's state:
|
||||
/// <https://material.io/design/interaction/states.html#anatomy>.
|
||||
/// {@endtemplate}
|
||||
final MaterialStateProperty<Color> dataRowColor;
|
||||
|
||||
/// {@template flutter.material.dataTable.dataRowHeight}
|
||||
/// The height of each row (excluding the row that contains column headings).
|
||||
/// {@endtemplate}
|
||||
///
|
||||
/// This value defaults to [kMinInteractiveDimension] to adhere to the Material
|
||||
/// This value defaults to kMinInteractiveDimension to adhere to the Material
|
||||
/// Design specifications.
|
||||
final double dataRowHeight;
|
||||
|
||||
/// {@template flutter.material.dataTable.dataTextStyle}
|
||||
/// The text style for data rows.
|
||||
/// {@endtemplate}
|
||||
///
|
||||
/// By default, the text style is [TextTheme.bodyText2].
|
||||
final TextStyle dataTextStyle;
|
||||
|
||||
/// {@template flutter.material.dataTable.headingRowColor}
|
||||
/// The background color for the heading row.
|
||||
///
|
||||
/// The effective background color can be made to depend on the
|
||||
/// [MaterialState] state, i.e. if the row is pressed, hovered, focused when
|
||||
/// sorted. The color is painted as an overlay to the row. To make sure that
|
||||
/// the row's [InkWell] is visible (when pressed, hovered and focused), it is
|
||||
/// recommended to use a translucent color.
|
||||
///
|
||||
/// ```dart
|
||||
/// DataTable(
|
||||
/// headingRowColor: MaterialStateProperty.resolveWith<Color>((Set<MaterialState> states) {
|
||||
/// if (states.contains(MaterialState.hovered))
|
||||
/// return Theme.of(context).colorScheme.primary.withOpacity(0.08);
|
||||
/// return null; // Use the default value.
|
||||
/// }),
|
||||
/// )
|
||||
/// ```
|
||||
///
|
||||
/// See also:
|
||||
///
|
||||
/// * The Material Design specification for overlay colors and how they
|
||||
/// match a component's state:
|
||||
/// <https://material.io/design/interaction/states.html#anatomy>.
|
||||
/// {@endtemplate}
|
||||
final MaterialStateProperty<Color> headingRowColor;
|
||||
|
||||
/// {@template flutter.material.dataTable.headingRowHeight}
|
||||
/// The height of the heading row.
|
||||
/// {@endtemplate}
|
||||
///
|
||||
/// This value defaults to 56.0 to adhere to the Material Design specifications.
|
||||
final double headingRowHeight;
|
||||
|
||||
/// {@template flutter.material.dataTable.headingTextStyle}
|
||||
/// The text style for the heading row.
|
||||
/// {@endtemplate}
|
||||
///
|
||||
/// By default, the text style is [TextTheme.subtitle2].
|
||||
final TextStyle headingTextStyle;
|
||||
|
||||
/// {@template flutter.material.dataTable.horizontalMargin}
|
||||
/// The horizontal margin between the edges of the table and the content
|
||||
/// in the first and last cells of each row.
|
||||
///
|
||||
/// When a checkbox is displayed, it is also the margin between the checkbox
|
||||
/// the content in the first data column.
|
||||
/// {@endtemplate}
|
||||
///
|
||||
/// This value defaults to 24.0 to adhere to the Material Design specifications.
|
||||
final double horizontalMargin;
|
||||
|
||||
/// {@template flutter.material.dataTable.columnSpacing}
|
||||
/// The horizontal margin between the contents of each data column.
|
||||
/// {@endtemplate}
|
||||
///
|
||||
/// This value defaults to 56.0 to adhere to the Material Design specifications.
|
||||
final double columnSpacing;
|
||||
@ -609,20 +517,6 @@ class DataTable extends StatelessWidget {
|
||||
/// Must be non-null, but may be empty.
|
||||
final List<DataRow> rows;
|
||||
|
||||
/// {@template flutter.material.dataTable.dividerThickness}
|
||||
/// The width of the divider that appears between [TableRow]s.
|
||||
///
|
||||
/// Must be greater than or equal to zero.
|
||||
/// {@endtemplate}
|
||||
/// This value defaults to 1.0.
|
||||
final double dividerThickness;
|
||||
|
||||
/// Whether a border at the bottom of the table is displayed.
|
||||
///
|
||||
/// By default, a border is not shown at the bottom to allow for a border
|
||||
/// around the table set with [DataTable.decoration].
|
||||
final bool showBottomBorder;
|
||||
|
||||
// Set by the constructor to the index of the only Column that is
|
||||
// non-numeric, if there is exactly one, otherwise null.
|
||||
final int _onlyTextColumn;
|
||||
@ -657,45 +551,29 @@ class DataTable extends StatelessWidget {
|
||||
}
|
||||
}
|
||||
|
||||
/// The default height of the heading row.
|
||||
static const double _headingRowHeight = 56.0;
|
||||
|
||||
/// The default horizontal margin between the edges of the table and the content
|
||||
/// in the first and last cells of each row.
|
||||
static const double _horizontalMargin = 24.0;
|
||||
|
||||
/// The default horizontal margin between the contents of each data column.
|
||||
static const double _columnSpacing = 56.0;
|
||||
|
||||
/// The default padding between the heading content and sort arrow.
|
||||
static const double _sortArrowPadding = 2.0;
|
||||
|
||||
/// The default divider thickness.
|
||||
static const double _dividerThickness = 1.0;
|
||||
|
||||
static const double _headingFontSize = 12.0;
|
||||
static const Duration _sortArrowAnimationDuration = Duration(milliseconds: 150);
|
||||
static const Color _grey100Opacity = Color(0x0A000000); // Grey 100 as opacity instead of solid color
|
||||
static const Color _grey300Opacity = Color(0x1E000000); // Dark theme variant is just a guess.
|
||||
|
||||
/// The width of the divider that appears between [TableRow]s.
|
||||
///
|
||||
/// Must be non-null and greater than or equal to zero.
|
||||
/// This value defaults to 1.0.
|
||||
final double dividerThickness;
|
||||
|
||||
Widget _buildCheckbox({
|
||||
BuildContext context,
|
||||
Color activeColor,
|
||||
bool checked,
|
||||
VoidCallback onRowTap,
|
||||
ValueChanged<bool> onCheckboxChanged,
|
||||
MaterialStateProperty<Color> overlayColor,
|
||||
}) {
|
||||
final ThemeData themeData = Theme.of(context);
|
||||
final double effectiveHorizontalMargin = horizontalMargin
|
||||
?? themeData.dataTableTheme.horizontalMargin
|
||||
?? _horizontalMargin;
|
||||
Widget contents = Semantics(
|
||||
container: true,
|
||||
child: Padding(
|
||||
padding: EdgeInsetsDirectional.only(
|
||||
start: effectiveHorizontalMargin,
|
||||
end: effectiveHorizontalMargin / 2.0,
|
||||
),
|
||||
padding: EdgeInsetsDirectional.only(start: horizontalMargin, end: horizontalMargin / 2.0),
|
||||
child: Center(
|
||||
child: Checkbox(
|
||||
activeColor: activeColor,
|
||||
@ -727,37 +605,39 @@ class DataTable extends StatelessWidget {
|
||||
VoidCallback onSort,
|
||||
bool sorted,
|
||||
bool ascending,
|
||||
MaterialStateProperty<Color> overlayColor,
|
||||
}) {
|
||||
final ThemeData themeData = Theme.of(context);
|
||||
List<Widget> arrowWithPadding() {
|
||||
return onSort == null ? const <Widget>[] : <Widget>[
|
||||
_SortArrow(
|
||||
visible: sorted,
|
||||
up: sorted ? ascending : null,
|
||||
duration: _sortArrowAnimationDuration,
|
||||
),
|
||||
const SizedBox(width: _sortArrowPadding),
|
||||
];
|
||||
}
|
||||
label = Row(
|
||||
textDirection: numeric ? TextDirection.rtl : null,
|
||||
children: <Widget>[
|
||||
label,
|
||||
if (onSort != null)
|
||||
...<Widget>[
|
||||
_SortArrow(
|
||||
visible: sorted,
|
||||
up: sorted ? ascending : null,
|
||||
duration: _sortArrowAnimationDuration,
|
||||
),
|
||||
const SizedBox(width: _sortArrowPadding),
|
||||
],
|
||||
...arrowWithPadding(),
|
||||
],
|
||||
);
|
||||
|
||||
final TextStyle effectiveHeadingTextStyle = headingTextStyle
|
||||
?? themeData.dataTableTheme.headingTextStyle
|
||||
?? themeData.textTheme.subtitle2;
|
||||
final double effectiveHeadingRowHeight = headingRowHeight
|
||||
?? themeData.dataTableTheme.headingRowHeight
|
||||
?? _headingRowHeight;
|
||||
label = Container(
|
||||
padding: padding,
|
||||
height: effectiveHeadingRowHeight,
|
||||
height: headingRowHeight,
|
||||
alignment: numeric ? Alignment.centerRight : AlignmentDirectional.centerStart,
|
||||
child: AnimatedDefaultTextStyle(
|
||||
style: effectiveHeadingTextStyle,
|
||||
style: TextStyle(
|
||||
// TODO(hansmuller): This should use the information provided by
|
||||
// textTheme/DataTableTheme, https://github.com/flutter/flutter/issues/56079
|
||||
fontWeight: FontWeight.w500,
|
||||
fontSize: _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),
|
||||
),
|
||||
softWrap: false,
|
||||
duration: _sortArrowAnimationDuration,
|
||||
child: label,
|
||||
@ -769,12 +649,10 @@ class DataTable extends StatelessWidget {
|
||||
child: label,
|
||||
);
|
||||
}
|
||||
|
||||
// TODO(dkwingsmt): Only wrap Inkwell if onSort != null. Blocked by
|
||||
// https://github.com/flutter/flutter/issues/51152
|
||||
label = InkWell(
|
||||
onTap: onSort,
|
||||
overlayColor: overlayColor,
|
||||
child: label,
|
||||
);
|
||||
return label;
|
||||
@ -791,7 +669,7 @@ class DataTable extends StatelessWidget {
|
||||
VoidCallback onSelectChanged,
|
||||
MaterialStateProperty<Color> overlayColor,
|
||||
}) {
|
||||
final ThemeData themeData = Theme.of(context);
|
||||
final bool isLightTheme = Theme.of(context).brightness == Brightness.light;
|
||||
if (showEditIcon) {
|
||||
const Widget icon = Icon(Icons.edit, size: 18.0);
|
||||
label = Expanded(child: label);
|
||||
@ -800,22 +678,25 @@ class DataTable extends StatelessWidget {
|
||||
children: <Widget>[ label, icon ],
|
||||
);
|
||||
}
|
||||
|
||||
final TextStyle effectiveDataTextStyle = dataTextStyle
|
||||
?? themeData.dataTableTheme.dataTextStyle
|
||||
?? themeData.textTheme.bodyText2;
|
||||
final double effectiveDataRowHeight = dataRowHeight
|
||||
?? themeData.dataTableTheme.dataRowHeight
|
||||
?? kMinInteractiveDimension;
|
||||
label = Container(
|
||||
padding: padding,
|
||||
height: effectiveDataRowHeight,
|
||||
height: dataRowHeight,
|
||||
alignment: numeric ? Alignment.centerRight : AlignmentDirectional.centerStart,
|
||||
child: DefaultTextStyle(
|
||||
style: effectiveDataTextStyle.copyWith(
|
||||
color: placeholder ? effectiveDataTextStyle.color.withOpacity(0.6) : null,
|
||||
style: TextStyle(
|
||||
// TODO(hansmuller): This should use the information provided by
|
||||
// textTheme/DataTableTheme, https://github.com/flutter/flutter/issues/56079
|
||||
fontSize: 13.0,
|
||||
color: isLightTheme
|
||||
? (placeholder ? Colors.black38 : Colors.black87)
|
||||
: (placeholder ? Colors.white38 : Colors.white70),
|
||||
),
|
||||
child: IconTheme.merge(
|
||||
data: IconThemeData(
|
||||
color: isLightTheme ? Colors.black54 : Colors.white70,
|
||||
),
|
||||
child: DropdownButtonHideUnderline(child: label),
|
||||
),
|
||||
child: DropdownButtonHideUnderline(child: label),
|
||||
),
|
||||
);
|
||||
if (onTap != null) {
|
||||
@ -839,16 +720,12 @@ class DataTable extends StatelessWidget {
|
||||
assert(!_debugInteractive || debugCheckHasMaterial(context));
|
||||
|
||||
final ThemeData theme = Theme.of(context);
|
||||
final MaterialStateProperty<Color> effectiveHeadingRowColor = headingRowColor
|
||||
?? theme.dataTableTheme.headingRowColor;
|
||||
final MaterialStateProperty<Color> effectiveDataRowColor = dataRowColor
|
||||
?? theme.dataTableTheme.dataRowColor;
|
||||
final MaterialStateProperty<Color> defaultRowColor = MaterialStateProperty.resolveWith(
|
||||
(Set<MaterialState> states) {
|
||||
if (states.contains(MaterialState.selected)) {
|
||||
// TODO(per): Add theming support for DataTable, https://github.com/flutter/flutter/issues/56079.
|
||||
// The color has to be transparent so you can see the ink on
|
||||
// the [Material].
|
||||
// TODO(perclasson): Align with Material specs, use translucent primary color: https://github.com/flutter/flutter/issues/64314.
|
||||
return (Theme.of(context).brightness == Brightness.light) ?
|
||||
_grey100Opacity : _grey300Opacity;
|
||||
}
|
||||
@ -858,12 +735,6 @@ class DataTable extends StatelessWidget {
|
||||
final bool anyRowSelectable = rows.any((DataRow row) => row.onSelectChanged != null);
|
||||
final bool displayCheckboxColumn = showCheckboxColumn && anyRowSelectable;
|
||||
final bool allChecked = displayCheckboxColumn && !rows.any((DataRow row) => row.onSelectChanged != null && !row.selected);
|
||||
final double effectiveHorizontalMargin = horizontalMargin
|
||||
?? theme.dataTableTheme.horizontalMargin
|
||||
?? _horizontalMargin;
|
||||
final double effectiveColumnSpacing = columnSpacing
|
||||
?? theme.dataTableTheme.columnSpacing
|
||||
?? _columnSpacing;
|
||||
|
||||
final List<TableColumnWidth> tableColumns = List<TableColumnWidth>(columns.length + (displayCheckboxColumn ? 1 : 0));
|
||||
final List<TableRow> tableRows = List<TableRow>.generate(
|
||||
@ -877,22 +748,13 @@ class DataTable extends StatelessWidget {
|
||||
if (isDisabled)
|
||||
MaterialState.disabled,
|
||||
};
|
||||
final Color resolvedDataRowColor = index > 0 ? (rows[index - 1].color ?? effectiveDataRowColor)?.resolve(states) : null;
|
||||
final Color resolvedHeadingRowColor = effectiveHeadingRowColor?.resolve(<MaterialState>{});
|
||||
final Color rowColor = index > 0 ? resolvedDataRowColor : resolvedHeadingRowColor;
|
||||
final BorderSide borderSide = Divider.createBorderSide(
|
||||
context,
|
||||
width: dividerThickness
|
||||
?? theme.dataTableTheme.dividerThickness
|
||||
?? _dividerThickness,
|
||||
);
|
||||
final Border border = showBottomBorder
|
||||
? Border(bottom: borderSide)
|
||||
: index == 0 ? null : Border(top: borderSide);
|
||||
final Color rowColor = index > 0 ? rows[index - 1].color?.resolve(states) : null;
|
||||
return TableRow(
|
||||
key: index == 0 ? _headingRowKey : rows[index - 1].key,
|
||||
decoration: BoxDecoration(
|
||||
border: border,
|
||||
border: Border(
|
||||
bottom: Divider.createBorderSide(context, width: dividerThickness),
|
||||
),
|
||||
color: rowColor ?? defaultRowColor.resolve(states),
|
||||
),
|
||||
children: List<Widget>(tableColumns.length),
|
||||
@ -904,9 +766,8 @@ class DataTable extends StatelessWidget {
|
||||
|
||||
int displayColumnIndex = 0;
|
||||
if (displayCheckboxColumn) {
|
||||
tableColumns[0] = FixedColumnWidth(effectiveHorizontalMargin + Checkbox.width + effectiveHorizontalMargin / 2.0);
|
||||
tableColumns[0] = FixedColumnWidth(horizontalMargin + Checkbox.width + horizontalMargin / 2.0);
|
||||
tableRows[0].children[0] = _buildCheckbox(
|
||||
context: context,
|
||||
activeColor: theme.accentColor,
|
||||
checked: allChecked,
|
||||
onCheckboxChanged: _handleSelectAll,
|
||||
@ -914,12 +775,11 @@ class DataTable extends StatelessWidget {
|
||||
rowIndex = 1;
|
||||
for (final DataRow row in rows) {
|
||||
tableRows[rowIndex].children[0] = _buildCheckbox(
|
||||
context: context,
|
||||
activeColor: theme.accentColor,
|
||||
checked: row.selected,
|
||||
onRowTap: () => row.onSelectChanged != null ? row.onSelectChanged(!row.selected) : null ,
|
||||
onCheckboxChanged: row.onSelectChanged,
|
||||
overlayColor: row.color ?? effectiveDataRowColor,
|
||||
overlayColor: row.color,
|
||||
);
|
||||
rowIndex += 1;
|
||||
}
|
||||
@ -931,18 +791,18 @@ class DataTable extends StatelessWidget {
|
||||
|
||||
double paddingStart;
|
||||
if (dataColumnIndex == 0 && displayCheckboxColumn) {
|
||||
paddingStart = effectiveHorizontalMargin / 2.0;
|
||||
paddingStart = horizontalMargin / 2.0;
|
||||
} else if (dataColumnIndex == 0 && !displayCheckboxColumn) {
|
||||
paddingStart = effectiveHorizontalMargin;
|
||||
paddingStart = horizontalMargin;
|
||||
} else {
|
||||
paddingStart = effectiveColumnSpacing / 2.0;
|
||||
paddingStart = columnSpacing / 2.0;
|
||||
}
|
||||
|
||||
double paddingEnd;
|
||||
if (dataColumnIndex == columns.length - 1) {
|
||||
paddingEnd = effectiveHorizontalMargin;
|
||||
paddingEnd = horizontalMargin;
|
||||
} else {
|
||||
paddingEnd = effectiveColumnSpacing / 2.0;
|
||||
paddingEnd = columnSpacing / 2.0;
|
||||
}
|
||||
|
||||
final EdgeInsetsDirectional padding = EdgeInsetsDirectional.only(
|
||||
@ -963,7 +823,6 @@ class DataTable extends StatelessWidget {
|
||||
onSort: column.onSort != null ? () => column.onSort(dataColumnIndex, sortColumnIndex != dataColumnIndex || !sortAscending) : null,
|
||||
sorted: dataColumnIndex == sortColumnIndex,
|
||||
ascending: sortAscending,
|
||||
overlayColor: effectiveHeadingRowColor,
|
||||
);
|
||||
rowIndex = 1;
|
||||
for (final DataRow row in rows) {
|
||||
@ -977,19 +836,16 @@ class DataTable extends StatelessWidget {
|
||||
showEditIcon: cell.showEditIcon,
|
||||
onTap: cell.onTap,
|
||||
onSelectChanged: () => row.onSelectChanged != null ? row.onSelectChanged(!row.selected) : null,
|
||||
overlayColor: row.color ?? effectiveDataRowColor,
|
||||
overlayColor: row.color,
|
||||
);
|
||||
rowIndex += 1;
|
||||
}
|
||||
displayColumnIndex += 1;
|
||||
}
|
||||
|
||||
return Ink(
|
||||
decoration: decoration ?? theme.dataTableTheme.decoration,
|
||||
child: Table(
|
||||
columnWidths: tableColumns.asMap(),
|
||||
children: tableRows,
|
||||
),
|
||||
return Table(
|
||||
columnWidths: tableColumns.asMap(),
|
||||
children: tableRows,
|
||||
);
|
||||
}
|
||||
}
|
||||
@ -1179,9 +1035,10 @@ class _SortArrowState extends State<_SortArrow> with TickerProviderStateMixin {
|
||||
transform: Matrix4.rotationZ(_orientationOffset + _orientationAnimation.value)
|
||||
..setTranslationRaw(0.0, _arrowIconBaselineOffset, 0.0),
|
||||
alignment: Alignment.center,
|
||||
child: const Icon(
|
||||
child: Icon(
|
||||
Icons.arrow_upward,
|
||||
size: _arrowIconSize,
|
||||
color: (Theme.of(context).brightness == Brightness.light) ? Colors.black87 : Colors.white70,
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
@ -1,250 +0,0 @@
|
||||
// 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.
|
||||
|
||||
// @dart = 2.8
|
||||
|
||||
import 'dart:ui' show lerpDouble;
|
||||
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter/widgets.dart';
|
||||
|
||||
import 'material_state.dart';
|
||||
import 'theme.dart';
|
||||
|
||||
/// Defines default property values for descendant [DataTable]
|
||||
/// widgets.
|
||||
///
|
||||
/// Descendant widgets obtain the current [DataTableThemeData] object
|
||||
/// using `DataTableTheme.of(context)`. Instances of
|
||||
/// [DataTableThemeData] can be customized with
|
||||
/// [DataTableThemeData.copyWith].
|
||||
///
|
||||
/// Typically a [DataTableThemeData] is specified as part of the
|
||||
/// overall [Theme] with [ThemeData.dataTableTheme].
|
||||
///
|
||||
/// All [DataTableThemeData] properties are `null` by default. When
|
||||
/// null, the [DataTable] will use the values from [ThemeData] if they exist,
|
||||
/// otherwise it will provide its own defaults based on the overall [Theme]'s
|
||||
/// textTheme and colorScheme. See the individual [DataTable] properties for
|
||||
/// details.
|
||||
///
|
||||
/// See also:
|
||||
///
|
||||
/// * [ThemeData], which describes the overall theme information for the
|
||||
/// application.
|
||||
@immutable
|
||||
class DataTableThemeData with Diagnosticable {
|
||||
/// Creates a theme that can be used for [ThemeData.dataTableTheme].
|
||||
const DataTableThemeData({
|
||||
this.decoration,
|
||||
this.dataRowColor,
|
||||
this.dataRowHeight,
|
||||
this.dataTextStyle,
|
||||
this.headingRowColor,
|
||||
this.headingRowHeight,
|
||||
this.headingTextStyle,
|
||||
this.horizontalMargin,
|
||||
this.columnSpacing,
|
||||
this.dividerThickness,
|
||||
});
|
||||
|
||||
/// {@macro flutter.material.dataTable.decoration}
|
||||
final Decoration decoration;
|
||||
|
||||
/// {@macro flutter.material.dataTable.dataRowColor}
|
||||
/// {@macro flutter.material.dataTable.dataRowColorCode}
|
||||
final MaterialStateProperty<Color> dataRowColor;
|
||||
|
||||
/// {@macro flutter.material.dataTable.dataRowHeight}
|
||||
final double dataRowHeight;
|
||||
|
||||
/// {@macro flutter.material.dataTable.dataTextStyle}
|
||||
final TextStyle dataTextStyle;
|
||||
|
||||
/// {@macro flutter.material.dataTable.headingRowColor}
|
||||
final MaterialStateProperty<Color> headingRowColor;
|
||||
|
||||
/// {@macro flutter.material.dataTable.headingRowHeight}
|
||||
final double headingRowHeight;
|
||||
|
||||
/// {@macro flutter.material.dataTable.headingTextStyle}
|
||||
final TextStyle headingTextStyle;
|
||||
|
||||
/// {@macro flutter.material.dataTable.horizontalMargin}
|
||||
final double horizontalMargin;
|
||||
|
||||
/// {@macro flutter.material.dataTable.columnSpacing}
|
||||
final double columnSpacing;
|
||||
|
||||
/// {@macro flutter.material.dataTable.dividerThickness}
|
||||
final double dividerThickness;
|
||||
|
||||
/// Creates a copy of this object but with the given fields replaced with the
|
||||
/// new values.
|
||||
DataTableThemeData copyWith({
|
||||
Decoration decoration,
|
||||
MaterialStateProperty<Color> dataRowColor,
|
||||
double dataRowHeight,
|
||||
TextStyle dataTextStyle,
|
||||
MaterialStateProperty<Color> headingRowColor,
|
||||
double headingRowHeight,
|
||||
TextStyle headingTextStyle,
|
||||
double horizontalMargin,
|
||||
double columnSpacing,
|
||||
double dividerThickness,
|
||||
}) {
|
||||
return DataTableThemeData(
|
||||
decoration: decoration ?? this.decoration,
|
||||
dataRowColor: dataRowColor ?? this.dataRowColor,
|
||||
dataRowHeight: dataRowHeight ?? this.dataRowHeight,
|
||||
dataTextStyle: dataTextStyle ?? this.dataTextStyle,
|
||||
headingRowColor: headingRowColor ?? this.headingRowColor,
|
||||
headingRowHeight: headingRowHeight ?? this.headingRowHeight,
|
||||
headingTextStyle: headingTextStyle ?? this.headingTextStyle,
|
||||
horizontalMargin: horizontalMargin ?? this.horizontalMargin,
|
||||
columnSpacing: columnSpacing ?? this.columnSpacing,
|
||||
dividerThickness: dividerThickness ?? this.dividerThickness,
|
||||
);
|
||||
}
|
||||
|
||||
/// Linearly interpolate between two [DataTableThemeData]s.
|
||||
///
|
||||
/// The argument `t` must not be null.
|
||||
///
|
||||
/// {@macro dart.ui.shadow.lerp}
|
||||
static DataTableThemeData lerp(DataTableThemeData a, DataTableThemeData b, double t) {
|
||||
assert(t != null);
|
||||
return DataTableThemeData(
|
||||
decoration: Decoration.lerp(a.decoration, b.decoration, t),
|
||||
dataRowColor: _lerpProperties(a.dataRowColor, b.dataRowColor, t, Color.lerp),
|
||||
dataRowHeight: lerpDouble(a.dataRowHeight, b.dataRowHeight, t),
|
||||
dataTextStyle: TextStyle.lerp(a.dataTextStyle, b.dataTextStyle, t),
|
||||
headingRowColor: _lerpProperties(a.headingRowColor, b.headingRowColor, t, Color.lerp),
|
||||
headingRowHeight: lerpDouble(a.headingRowHeight, b.headingRowHeight, t),
|
||||
headingTextStyle: TextStyle.lerp(a.headingTextStyle, b.headingTextStyle, t),
|
||||
horizontalMargin: lerpDouble(a.horizontalMargin, b.horizontalMargin, t),
|
||||
columnSpacing: lerpDouble(a.columnSpacing, b.columnSpacing, t),
|
||||
dividerThickness: lerpDouble(a.dividerThickness, b.dividerThickness, t)
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
int get hashCode {
|
||||
return hashValues(
|
||||
decoration,
|
||||
dataRowColor,
|
||||
dataRowHeight,
|
||||
dataTextStyle,
|
||||
headingRowColor,
|
||||
headingRowHeight,
|
||||
headingTextStyle,
|
||||
horizontalMargin,
|
||||
columnSpacing,
|
||||
dividerThickness,
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
if (identical(this, other))
|
||||
return true;
|
||||
if (other.runtimeType != runtimeType)
|
||||
return false;
|
||||
return other is DataTableThemeData
|
||||
&& other.decoration == decoration
|
||||
&& other.dataRowColor == dataRowColor
|
||||
&& other.dataRowHeight == dataRowHeight
|
||||
&& other.dataTextStyle == dataTextStyle
|
||||
&& other.headingRowColor == headingRowColor
|
||||
&& other.headingRowHeight == headingRowHeight
|
||||
&& other.headingTextStyle == headingTextStyle
|
||||
&& other.horizontalMargin == horizontalMargin
|
||||
&& other.columnSpacing == columnSpacing
|
||||
&& other.dividerThickness == dividerThickness;
|
||||
}
|
||||
|
||||
@override
|
||||
void debugFillProperties(DiagnosticPropertiesBuilder properties) {
|
||||
super.debugFillProperties(properties);
|
||||
properties.add(DiagnosticsProperty<Decoration>('decoration', decoration, defaultValue: null));
|
||||
properties.add(DiagnosticsProperty<MaterialStateProperty<Color>>('dataRowColor', dataRowColor, defaultValue: null));
|
||||
properties.add(DoubleProperty('dataRowHeight', dataRowHeight, defaultValue: null));
|
||||
properties.add(DiagnosticsProperty<TextStyle>('dataTextStyle', dataTextStyle, defaultValue: null));
|
||||
properties.add(DiagnosticsProperty<MaterialStateProperty<Color>>('headingRowColor', headingRowColor, defaultValue: null));
|
||||
properties.add(DoubleProperty('headingRowHeight', headingRowHeight, defaultValue: null));
|
||||
properties.add(DiagnosticsProperty<TextStyle>('headingTextStyle', headingTextStyle, defaultValue: null));
|
||||
properties.add(DoubleProperty('horizontalMargin', horizontalMargin, defaultValue: null));
|
||||
properties.add(DoubleProperty('columnSpacing', columnSpacing, defaultValue: null));
|
||||
properties.add(DoubleProperty('dividerThickness', dividerThickness, defaultValue: null));
|
||||
}
|
||||
|
||||
static MaterialStateProperty<T> _lerpProperties<T>(MaterialStateProperty<T> a, MaterialStateProperty<T> b, double t, T Function(T, T, double) lerpFunction ) {
|
||||
// Avoid creating a _LerpProperties object for a common case.
|
||||
if (a == null && b == null)
|
||||
return null;
|
||||
return _LerpProperties<T>(a, b, t, lerpFunction);
|
||||
}
|
||||
}
|
||||
|
||||
class _LerpProperties<T> implements MaterialStateProperty<T> {
|
||||
const _LerpProperties(this.a, this.b, this.t, this.lerpFunction);
|
||||
|
||||
final MaterialStateProperty<T> a;
|
||||
final MaterialStateProperty<T> b;
|
||||
final double t;
|
||||
final T Function(T, T, double) lerpFunction;
|
||||
|
||||
@override
|
||||
T resolve(Set<MaterialState> states) {
|
||||
final T resolvedA = a?.resolve(states);
|
||||
final T resolvedB = b?.resolve(states);
|
||||
return lerpFunction(resolvedA, resolvedB, t);
|
||||
}
|
||||
}
|
||||
|
||||
/// Applies a data table theme to descendant [DataTable] widgets.
|
||||
///
|
||||
/// Descendant widgets obtain the current theme's [DataTableTheme] object using
|
||||
/// [DataTableTheme.of]. When a widget uses [DataTableTheme.of], it is
|
||||
/// automatically rebuilt if the theme later changes.
|
||||
///
|
||||
/// A data table theme can be specified as part of the overall Material
|
||||
/// theme using [ThemeData.dataTableTheme].
|
||||
///
|
||||
/// See also:
|
||||
///
|
||||
/// * [DataTableThemeData], which describes the actual configuration
|
||||
/// of a data table theme.
|
||||
class DataTableTheme extends InheritedWidget {
|
||||
/// Constructs a data table theme that configures all descendant
|
||||
/// [DataTable] widgets.
|
||||
///
|
||||
/// The [data] must not be null.
|
||||
const DataTableTheme({
|
||||
Key key,
|
||||
@required this.data,
|
||||
Widget child,
|
||||
}) : assert(data != null), super(key: key, child: child);
|
||||
|
||||
/// The properties used for all descendant [DataTable] widgets.
|
||||
final DataTableThemeData data;
|
||||
|
||||
/// Returns the configuration [data] from the closest
|
||||
/// [DataTableTheme] ancestor. If there is no ancestor, it returns
|
||||
/// [ThemeData.dataTableTheme]. Applications can assume that the
|
||||
/// returned value will not be null.
|
||||
///
|
||||
/// Typical usage is as follows:
|
||||
///
|
||||
/// ```dart
|
||||
/// DataTableThemeData theme = DataTableTheme.of(context);
|
||||
/// ```
|
||||
static DataTableThemeData of(BuildContext context) {
|
||||
final DataTableTheme dataTableTheme = context.dependOnInheritedWidgetOfExactType<DataTableTheme>();
|
||||
return dataTableTheme?.data ?? Theme.of(context).dataTableTheme;
|
||||
}
|
||||
|
||||
@override
|
||||
bool updateShouldNotify(DataTableTheme oldWidget) => data != oldWidget.data;
|
||||
}
|
||||
@ -476,7 +476,6 @@ class PaginatedDataTableState extends State<PaginatedDataTable> {
|
||||
horizontalMargin: widget.horizontalMargin,
|
||||
columnSpacing: widget.columnSpacing,
|
||||
showCheckboxColumn: widget.showCheckboxColumn,
|
||||
showBottomBorder: true,
|
||||
rows: _getRows(_firstRowIndex, widget.rowsPerPage),
|
||||
),
|
||||
),
|
||||
|
||||
@ -22,7 +22,6 @@ import 'card_theme.dart';
|
||||
import 'chip_theme.dart';
|
||||
import 'color_scheme.dart';
|
||||
import 'colors.dart';
|
||||
import 'data_table_theme.dart';
|
||||
import 'dialog_theme.dart';
|
||||
import 'divider_theme.dart';
|
||||
import 'elevated_button_theme.dart';
|
||||
@ -284,7 +283,6 @@ class ThemeData with Diagnosticable {
|
||||
ElevatedButtonThemeData elevatedButtonTheme,
|
||||
OutlinedButtonThemeData outlinedButtonTheme,
|
||||
TextSelectionThemeData textSelectionTheme,
|
||||
DataTableThemeData dataTableTheme,
|
||||
bool fixTextFieldOutlineLabel,
|
||||
bool useTextSelectionTheme,
|
||||
}) {
|
||||
@ -402,7 +400,6 @@ class ThemeData with Diagnosticable {
|
||||
elevatedButtonTheme ??= const ElevatedButtonThemeData();
|
||||
outlinedButtonTheme ??= const OutlinedButtonThemeData();
|
||||
textSelectionTheme ??= const TextSelectionThemeData();
|
||||
dataTableTheme ??= const DataTableThemeData();
|
||||
|
||||
fixTextFieldOutlineLabel ??= false;
|
||||
useTextSelectionTheme ??= false;
|
||||
@ -478,7 +475,6 @@ class ThemeData with Diagnosticable {
|
||||
elevatedButtonTheme: elevatedButtonTheme,
|
||||
outlinedButtonTheme: outlinedButtonTheme,
|
||||
textSelectionTheme: textSelectionTheme,
|
||||
dataTableTheme: dataTableTheme,
|
||||
fixTextFieldOutlineLabel: fixTextFieldOutlineLabel,
|
||||
useTextSelectionTheme: useTextSelectionTheme,
|
||||
);
|
||||
@ -565,7 +561,6 @@ class ThemeData with Diagnosticable {
|
||||
@required this.elevatedButtonTheme,
|
||||
@required this.outlinedButtonTheme,
|
||||
@required this.textSelectionTheme,
|
||||
@required this.dataTableTheme,
|
||||
@required this.fixTextFieldOutlineLabel,
|
||||
@required this.useTextSelectionTheme,
|
||||
}) : assert(visualDensity != null),
|
||||
@ -634,8 +629,8 @@ class ThemeData with Diagnosticable {
|
||||
assert(textButtonTheme != null),
|
||||
assert(elevatedButtonTheme != null),
|
||||
assert(outlinedButtonTheme != null),
|
||||
assert(fixTextFieldOutlineLabel != null),
|
||||
assert(textSelectionTheme != null),
|
||||
assert(dataTableTheme != null),
|
||||
assert(fixTextFieldOutlineLabel != null),
|
||||
assert(useTextSelectionTheme != null);
|
||||
|
||||
@ -1112,10 +1107,6 @@ class ThemeData with Diagnosticable {
|
||||
/// A theme for customizing the appearance and layout of [TextField] widgets.
|
||||
final TextSelectionThemeData textSelectionTheme;
|
||||
|
||||
/// A theme for customizing the appearance and layout of [DataTable]
|
||||
/// widgets.
|
||||
final DataTableThemeData dataTableTheme;
|
||||
|
||||
/// A temporary flag to allow apps to opt-in to a
|
||||
/// [small fix](https://github.com/flutter/flutter/issues/54028) for the Y
|
||||
/// coordinate of the floating label in a [TextField] [OutlineInputBorder].
|
||||
@ -1215,7 +1206,6 @@ class ThemeData with Diagnosticable {
|
||||
ElevatedButtonThemeData elevatedButtonTheme,
|
||||
OutlinedButtonThemeData outlinedButtonTheme,
|
||||
TextSelectionThemeData textSelectionTheme,
|
||||
DataTableThemeData dataTableTheme,
|
||||
bool fixTextFieldOutlineLabel,
|
||||
bool useTextSelectionTheme,
|
||||
}) {
|
||||
@ -1291,7 +1281,6 @@ class ThemeData with Diagnosticable {
|
||||
elevatedButtonTheme: elevatedButtonTheme ?? this.elevatedButtonTheme,
|
||||
outlinedButtonTheme: outlinedButtonTheme ?? this.outlinedButtonTheme,
|
||||
textSelectionTheme: textSelectionTheme ?? this.textSelectionTheme,
|
||||
dataTableTheme: dataTableTheme ?? this.dataTableTheme,
|
||||
fixTextFieldOutlineLabel: fixTextFieldOutlineLabel ?? this.fixTextFieldOutlineLabel,
|
||||
useTextSelectionTheme: useTextSelectionTheme ?? this.useTextSelectionTheme,
|
||||
);
|
||||
@ -1445,7 +1434,6 @@ class ThemeData with Diagnosticable {
|
||||
elevatedButtonTheme: ElevatedButtonThemeData.lerp(a.elevatedButtonTheme, b.elevatedButtonTheme, t),
|
||||
outlinedButtonTheme: OutlinedButtonThemeData.lerp(a.outlinedButtonTheme, b.outlinedButtonTheme, t),
|
||||
textSelectionTheme: TextSelectionThemeData .lerp(a.textSelectionTheme, b.textSelectionTheme, t),
|
||||
dataTableTheme: DataTableThemeData.lerp(a.dataTableTheme, b.dataTableTheme, t),
|
||||
fixTextFieldOutlineLabel: t < 0.5 ? a.fixTextFieldOutlineLabel : b.fixTextFieldOutlineLabel,
|
||||
useTextSelectionTheme: t < 0.5 ? a.useTextSelectionTheme : b.useTextSelectionTheme,
|
||||
);
|
||||
@ -1527,7 +1515,6 @@ class ThemeData with Diagnosticable {
|
||||
&& other.elevatedButtonTheme == elevatedButtonTheme
|
||||
&& other.outlinedButtonTheme == outlinedButtonTheme
|
||||
&& other.textSelectionTheme == textSelectionTheme
|
||||
&& other.dataTableTheme == dataTableTheme
|
||||
&& other.fixTextFieldOutlineLabel == fixTextFieldOutlineLabel
|
||||
&& other.useTextSelectionTheme == useTextSelectionTheme;
|
||||
}
|
||||
@ -1608,7 +1595,6 @@ class ThemeData with Diagnosticable {
|
||||
elevatedButtonTheme,
|
||||
outlinedButtonTheme,
|
||||
textSelectionTheme,
|
||||
dataTableTheme,
|
||||
fixTextFieldOutlineLabel,
|
||||
useTextSelectionTheme,
|
||||
];
|
||||
@ -1687,7 +1673,6 @@ class ThemeData with Diagnosticable {
|
||||
properties.add(DiagnosticsProperty<TextButtonThemeData>('textButtonTheme', textButtonTheme, defaultValue: defaultData.textButtonTheme, level: DiagnosticLevel.debug));
|
||||
properties.add(DiagnosticsProperty<ElevatedButtonThemeData>('elevatedButtonTheme', elevatedButtonTheme, defaultValue: defaultData.elevatedButtonTheme, level: DiagnosticLevel.debug));
|
||||
properties.add(DiagnosticsProperty<OutlinedButtonThemeData>('outlinedButtonTheme', outlinedButtonTheme, defaultValue: defaultData.outlinedButtonTheme, level: DiagnosticLevel.debug));
|
||||
properties.add(DiagnosticsProperty<DataTableThemeData>('dataTableTheme', dataTableTheme, defaultValue: defaultData.dataTableTheme, level: DiagnosticLevel.debug));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -177,10 +177,6 @@ void main() {
|
||||
MaterialApp(
|
||||
home: Material(
|
||||
child: DataTable(
|
||||
headingTextStyle: const TextStyle(
|
||||
fontSize: 14.0,
|
||||
letterSpacing: 0.0, // Will overflow if letter spacing is larger than 0.0.
|
||||
),
|
||||
columns: <DataColumn>[
|
||||
DataColumn(
|
||||
label: Text('X' * 2000),
|
||||
@ -199,7 +195,6 @@ void main() {
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
expect(tester.renderObject<RenderBox>(find.byType(Text).first).size.width, greaterThan(800.0));
|
||||
expect(tester.renderObject<RenderBox>(find.byType(Row).first).size.width, greaterThan(800.0));
|
||||
expect(tester.takeException(), isNull); // column overflows table, but text doesn't overflow cell
|
||||
@ -697,7 +692,7 @@ void main() {
|
||||
);
|
||||
|
||||
// custom first column padding
|
||||
padding = find.widgetWithText(Padding, 'Frozen yogurt').first;
|
||||
padding = find.widgetWithText(Padding, 'Frozen yogurt');
|
||||
cellContent = find.widgetWithText(Align, 'Frozen yogurt'); // DataTable wraps its DataCells in an Align widget
|
||||
expect(
|
||||
tester.getRect(cellContent).left - tester.getRect(padding).left,
|
||||
@ -957,9 +952,9 @@ void main() {
|
||||
);
|
||||
|
||||
Table table = tester.widget(find.byType(Table));
|
||||
TableRow tableRow = table.children.last;
|
||||
TableRow tableRow = table.children.first;
|
||||
BoxDecoration boxDecoration = tableRow.decoration as BoxDecoration;
|
||||
expect(boxDecoration.border.top.width, 1.0);
|
||||
expect(boxDecoration.border.bottom.width, 1.0);
|
||||
|
||||
const double thickness = 4.2;
|
||||
await tester.pumpWidget(
|
||||
@ -974,58 +969,9 @@ void main() {
|
||||
),
|
||||
);
|
||||
table = tester.widget(find.byType(Table));
|
||||
tableRow = table.children.last;
|
||||
tableRow = table.children.first;
|
||||
boxDecoration = tableRow.decoration as BoxDecoration;
|
||||
expect(boxDecoration.border.top.width, thickness);
|
||||
});
|
||||
|
||||
testWidgets('DataTable set show bottom border', (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: DataTable(
|
||||
showBottomBorder: true,
|
||||
columns: columns,
|
||||
rows: rows,
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
Table table = tester.widget(find.byType(Table));
|
||||
TableRow tableRow = table.children.last;
|
||||
BoxDecoration boxDecoration = tableRow.decoration as BoxDecoration;
|
||||
expect(boxDecoration.border.bottom.width, 1.0);
|
||||
|
||||
await tester.pumpWidget(
|
||||
MaterialApp(
|
||||
home: Material(
|
||||
child: DataTable(
|
||||
columns: columns,
|
||||
rows: rows,
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
table = tester.widget(find.byType(Table));
|
||||
tableRow = table.children.last;
|
||||
boxDecoration = tableRow.decoration as BoxDecoration;
|
||||
expect(boxDecoration.border.bottom.width, 0.0);
|
||||
expect(boxDecoration.border.bottom.width, thickness);
|
||||
});
|
||||
|
||||
testWidgets('DataTable column heading cell - with and without sorting', (WidgetTester tester) async {
|
||||
@ -1279,7 +1225,7 @@ void main() {
|
||||
final TestGesture gesture = await tester.startGesture(tester.getCenter(find.text('Content1')));
|
||||
await tester.pump(const Duration(milliseconds: 200)); // splash is well underway
|
||||
final RenderBox box = Material.of(tester.element(find.byType(InkWell))) as RenderBox;
|
||||
expect(box, paints..circle(x: 68.0, y: 24.0, color: pressedColor));
|
||||
expect(box, paints..circle(x: 64.0, y: 24.0, color: pressedColor));
|
||||
await gesture.up();
|
||||
});
|
||||
}
|
||||
|
||||
@ -1,268 +0,0 @@
|
||||
// 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.
|
||||
|
||||
// @dart = 2.8
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/rendering.dart';
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
|
||||
void main() {
|
||||
test('DataTableThemeData copyWith, ==, hashCode basics', () {
|
||||
expect(const DataTableThemeData(), const DataTableThemeData().copyWith());
|
||||
expect(const DataTableThemeData().hashCode, const DataTableThemeData().copyWith().hashCode);
|
||||
});
|
||||
|
||||
test('DataTableThemeData defaults', () {
|
||||
const DataTableThemeData themeData = DataTableThemeData();
|
||||
expect(themeData.decoration, null);
|
||||
expect(themeData.dataRowColor, null);
|
||||
expect(themeData.dataRowHeight, null);
|
||||
expect(themeData.dataTextStyle, null);
|
||||
expect(themeData.headingRowColor, null);
|
||||
expect(themeData.headingRowHeight, null);
|
||||
expect(themeData.headingTextStyle, null);
|
||||
expect(themeData.horizontalMargin, null);
|
||||
expect(themeData.columnSpacing, null);
|
||||
expect(themeData.dividerThickness, null);
|
||||
|
||||
const DataTableTheme theme = DataTableTheme(data: DataTableThemeData());
|
||||
expect(theme.data.decoration, null);
|
||||
expect(theme.data.dataRowColor, null);
|
||||
expect(theme.data.dataRowHeight, null);
|
||||
expect(theme.data.dataTextStyle, null);
|
||||
expect(theme.data.headingRowColor, null);
|
||||
expect(theme.data.headingRowHeight, null);
|
||||
expect(theme.data.headingTextStyle, null);
|
||||
expect(theme.data.horizontalMargin, null);
|
||||
expect(theme.data.columnSpacing, null);
|
||||
expect(theme.data.dividerThickness, null);
|
||||
});
|
||||
|
||||
testWidgets('Default DataTableThemeData debugFillProperties', (WidgetTester tester) async {
|
||||
final DiagnosticPropertiesBuilder builder = DiagnosticPropertiesBuilder();
|
||||
const DataTableThemeData().debugFillProperties(builder);
|
||||
|
||||
final List<String> description = builder.properties
|
||||
.where((DiagnosticsNode node) => !node.isFiltered(DiagnosticLevel.info))
|
||||
.map((DiagnosticsNode node) => node.toString())
|
||||
.toList();
|
||||
|
||||
expect(description, <String>[]);
|
||||
});
|
||||
|
||||
testWidgets('DataTableThemeData implements debugFillProperties', (WidgetTester tester) async {
|
||||
final DiagnosticPropertiesBuilder builder = DiagnosticPropertiesBuilder();
|
||||
DataTableThemeData(
|
||||
decoration: const BoxDecoration(color: Color(0xfffffff0)),
|
||||
dataRowColor: MaterialStateProperty.resolveWith<Color>(
|
||||
(Set<MaterialState> states) => const Color(0xfffffff1),
|
||||
),
|
||||
dataRowHeight: 51.0,
|
||||
dataTextStyle: const TextStyle(fontSize: 12.0),
|
||||
headingRowColor: MaterialStateProperty.resolveWith<Color>(
|
||||
(Set<MaterialState> states) => const Color(0xfffffff2),
|
||||
),
|
||||
headingRowHeight: 52.0,
|
||||
headingTextStyle: const TextStyle(fontSize: 14.0),
|
||||
horizontalMargin: 3.0,
|
||||
columnSpacing: 4.0,
|
||||
dividerThickness: 5.0,
|
||||
).debugFillProperties(builder);
|
||||
|
||||
final List<String> description = builder.properties
|
||||
.where((DiagnosticsNode node) => !node.isFiltered(DiagnosticLevel.info))
|
||||
.map((DiagnosticsNode node) => node.toString())
|
||||
.toList();
|
||||
|
||||
expect(description[0], 'decoration: BoxDecoration(color: Color(0xfffffff0))');
|
||||
expect(description[1], 'dataRowColor: Instance of \'_MaterialStatePropertyWith<Color>\'');
|
||||
expect(description[2], 'dataRowHeight: 51.0');
|
||||
expect(description[3], 'dataTextStyle: TextStyle(inherit: true, size: 12.0)');
|
||||
expect(description[4], 'headingRowColor: Instance of \'_MaterialStatePropertyWith<Color>\'');
|
||||
expect(description[5], 'headingRowHeight: 52.0');
|
||||
expect(description[6], 'headingTextStyle: TextStyle(inherit: true, size: 14.0)');
|
||||
expect(description[7], 'horizontalMargin: 3.0');
|
||||
expect(description[8], 'columnSpacing: 4.0');
|
||||
expect(description[9], 'dividerThickness: 5.0');
|
||||
});
|
||||
|
||||
testWidgets('DataTable is themeable', (WidgetTester tester) async {
|
||||
const BoxDecoration decoration = BoxDecoration(color: Color(0xfffffff0));
|
||||
final MaterialStateProperty<Color> dataRowColor = MaterialStateProperty.resolveWith<Color>(
|
||||
(Set<MaterialState> states) => const Color(0xfffffff1),
|
||||
);
|
||||
const double dataRowHeight = 51.0;
|
||||
const TextStyle dataTextStyle = TextStyle(fontSize: 12.5);
|
||||
final MaterialStateProperty<Color> headingRowColor = MaterialStateProperty.resolveWith<Color>(
|
||||
(Set<MaterialState> states) => const Color(0xfffffff2),
|
||||
);
|
||||
const double headingRowHeight = 52.0;
|
||||
const TextStyle headingTextStyle = TextStyle(fontSize: 14.5);
|
||||
const double horizontalMargin = 3.0;
|
||||
const double columnSpacing = 4.0;
|
||||
const double dividerThickness = 5.0;
|
||||
|
||||
await tester.pumpWidget(
|
||||
MaterialApp(
|
||||
theme: ThemeData(
|
||||
dataTableTheme: DataTableThemeData(
|
||||
decoration: decoration,
|
||||
dataRowColor: dataRowColor,
|
||||
dataRowHeight: dataRowHeight,
|
||||
dataTextStyle: dataTextStyle,
|
||||
headingRowColor: headingRowColor,
|
||||
headingRowHeight: headingRowHeight,
|
||||
headingTextStyle: headingTextStyle,
|
||||
horizontalMargin: horizontalMargin,
|
||||
columnSpacing: columnSpacing,
|
||||
dividerThickness: dividerThickness,
|
||||
),
|
||||
),
|
||||
home: Scaffold(
|
||||
body: DataTable(
|
||||
sortColumnIndex: 0,
|
||||
columns: <DataColumn>[
|
||||
DataColumn(
|
||||
label: const Text('A'),
|
||||
onSort: (int columnIndex, bool ascending) {},
|
||||
),
|
||||
const DataColumn(label: Text('B')),
|
||||
],
|
||||
rows: const <DataRow>[
|
||||
DataRow(cells: <DataCell>[
|
||||
DataCell(Text('Data')),
|
||||
DataCell(Text('Data 2')),
|
||||
]),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
final Finder dataTableInkFinder = find.descendant(of: find.byType(DataTable), matching: find.byType(Ink));
|
||||
expect(tester.widgetList<Ink>(dataTableInkFinder).last.decoration, decoration);
|
||||
|
||||
final TextStyle dataRowTextStyle = tester.renderObject<RenderParagraph>(find.text('Data')).text.style;
|
||||
expect(dataRowTextStyle.fontSize, dataTextStyle.fontSize);
|
||||
expect(_tableRowBoxDecoration(tester: tester, index: 1).color, dataRowColor.resolve(<MaterialState>{}));
|
||||
expect(_tableRowBoxDecoration(tester: tester, index: 1).border.top.width, dividerThickness);
|
||||
|
||||
final Finder dataRowContainer = find.ancestor(of: find.text('Data'), matching: find.byType(Container));
|
||||
expect(tester.getSize(dataRowContainer).height, dataRowHeight);
|
||||
|
||||
final TextStyle headingRowTextStyle = tester.renderObject<RenderParagraph>(find.text('A')).text.style;
|
||||
expect(headingRowTextStyle.fontSize, headingTextStyle.fontSize);
|
||||
expect(_tableRowBoxDecoration(tester: tester, index: 0).color, headingRowColor.resolve(<MaterialState>{}));
|
||||
|
||||
final Finder headingRowContainer = find.ancestor(of: find.text('A'), matching: find.byType(Container));
|
||||
expect(tester.getSize(headingRowContainer).height, headingRowHeight);
|
||||
expect(tester.getTopLeft(find.text('A')).dx, horizontalMargin);
|
||||
expect(tester.getTopLeft(find.text('Data 2')).dx - tester.getTopRight(find.text('Data')).dx, columnSpacing);
|
||||
});
|
||||
|
||||
testWidgets('DataTable properties are taken over the theme values', (WidgetTester tester) async {
|
||||
const BoxDecoration themeDecoration = BoxDecoration(color: Color(0xfffffff1));
|
||||
final MaterialStateProperty<Color> themeDataRowColor = MaterialStateProperty.resolveWith<Color>(
|
||||
(Set<MaterialState> states) => const Color(0xfffffff0),
|
||||
);
|
||||
const double themeDataRowHeight = 50.0;
|
||||
const TextStyle themeDataTextStyle = TextStyle(fontSize: 11.5);
|
||||
final MaterialStateProperty<Color> themeHeadingRowColor = MaterialStateProperty.resolveWith<Color>(
|
||||
(Set<MaterialState> states) => const Color(0xfffffff1),
|
||||
);
|
||||
const double themeHeadingRowHeight = 51.0;
|
||||
const TextStyle themeHeadingTextStyle = TextStyle(fontSize: 13.5);
|
||||
const double themeHorizontalMargin = 2.0;
|
||||
const double themeColumnSpacing = 3.0;
|
||||
const double themeDividerThickness = 4.0;
|
||||
|
||||
const BoxDecoration decoration = BoxDecoration(color: Color(0xfffffff0));
|
||||
final MaterialStateProperty<Color> dataRowColor = MaterialStateProperty.resolveWith<Color>(
|
||||
(Set<MaterialState> states) => const Color(0xfffffff1),
|
||||
);
|
||||
const double dataRowHeight = 51.0;
|
||||
const TextStyle dataTextStyle = TextStyle(fontSize: 12.5);
|
||||
final MaterialStateProperty<Color> headingRowColor = MaterialStateProperty.resolveWith<Color>(
|
||||
(Set<MaterialState> states) => const Color(0xfffffff2),
|
||||
);
|
||||
const double headingRowHeight = 52.0;
|
||||
const TextStyle headingTextStyle = TextStyle(fontSize: 14.5);
|
||||
const double horizontalMargin = 3.0;
|
||||
const double columnSpacing = 4.0;
|
||||
const double dividerThickness = 5.0;
|
||||
await tester.pumpWidget(
|
||||
MaterialApp(
|
||||
theme: ThemeData(
|
||||
dataTableTheme: DataTableThemeData(
|
||||
decoration: themeDecoration,
|
||||
dataRowColor: themeDataRowColor,
|
||||
dataRowHeight: themeDataRowHeight,
|
||||
dataTextStyle: themeDataTextStyle,
|
||||
headingRowColor: themeHeadingRowColor,
|
||||
headingRowHeight: themeHeadingRowHeight,
|
||||
headingTextStyle: themeHeadingTextStyle,
|
||||
horizontalMargin: themeHorizontalMargin,
|
||||
columnSpacing: themeColumnSpacing,
|
||||
dividerThickness: themeDividerThickness,
|
||||
),
|
||||
),
|
||||
home: Scaffold(
|
||||
body: DataTable(
|
||||
decoration: decoration,
|
||||
dataRowColor: dataRowColor,
|
||||
dataRowHeight: dataRowHeight,
|
||||
dataTextStyle: dataTextStyle,
|
||||
headingRowColor: headingRowColor,
|
||||
headingRowHeight: headingRowHeight,
|
||||
headingTextStyle: headingTextStyle,
|
||||
horizontalMargin: horizontalMargin,
|
||||
columnSpacing: columnSpacing,
|
||||
dividerThickness: dividerThickness,
|
||||
sortColumnIndex: 0,
|
||||
columns: <DataColumn>[
|
||||
DataColumn(
|
||||
label: const Text('A'),
|
||||
onSort: (int columnIndex, bool ascending) {},
|
||||
),
|
||||
const DataColumn(label: Text('B')),
|
||||
],
|
||||
rows: const <DataRow>[
|
||||
DataRow(cells: <DataCell>[
|
||||
DataCell(Text('Data')),
|
||||
DataCell(Text('Data 2')),
|
||||
]),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
final Finder dataTableInkFinder = find.descendant(of: find.byType(DataTable), matching: find.byType(Ink));
|
||||
expect(tester.widgetList<Ink>(dataTableInkFinder).last.decoration, decoration);
|
||||
|
||||
final TextStyle dataRowTextStyle = tester.renderObject<RenderParagraph>(find.text('Data')).text.style;
|
||||
expect(dataRowTextStyle.fontSize, dataTextStyle.fontSize);
|
||||
expect(_tableRowBoxDecoration(tester: tester, index: 1).color, dataRowColor.resolve(<MaterialState>{}));
|
||||
expect(_tableRowBoxDecoration(tester: tester, index: 1).border.top.width, dividerThickness);
|
||||
|
||||
final Finder dataRowContainer = find.ancestor(of: find.text('Data'), matching: find.byType(Container));
|
||||
expect(tester.getSize(dataRowContainer).height, dataRowHeight);
|
||||
|
||||
final TextStyle headingRowTextStyle = tester.renderObject<RenderParagraph>(find.text('A')).text.style;
|
||||
expect(headingRowTextStyle.fontSize, headingTextStyle.fontSize);
|
||||
expect(_tableRowBoxDecoration(tester: tester, index: 0).color, headingRowColor.resolve(<MaterialState>{}));
|
||||
|
||||
final Finder headingRowContainer = find.ancestor(of: find.text('A'), matching: find.byType(Container));
|
||||
expect(tester.getSize(headingRowContainer).height, headingRowHeight);
|
||||
expect(tester.getTopLeft(find.text('A')).dx, horizontalMargin);
|
||||
expect(tester.getTopLeft(find.text('Data 2')).dx - tester.getTopRight(find.text('Data')).dx, columnSpacing);
|
||||
});
|
||||
}
|
||||
|
||||
BoxDecoration _tableRowBoxDecoration({WidgetTester tester, int index}) {
|
||||
final Table table = tester.widget(find.byType(Table));
|
||||
final TableRow tableRow = table.children[index];
|
||||
return tableRow.decoration as BoxDecoration;
|
||||
}
|
||||
@ -288,7 +288,6 @@ void main() {
|
||||
elevatedButtonTheme: ElevatedButtonThemeData(style: ElevatedButton.styleFrom(primary: Colors.green)),
|
||||
outlinedButtonTheme: OutlinedButtonThemeData(style: OutlinedButton.styleFrom(primary: Colors.blue)),
|
||||
textSelectionTheme: const TextSelectionThemeData(cursorColor: Colors.black),
|
||||
dataTableTheme: const DataTableThemeData(),
|
||||
fixTextFieldOutlineLabel: false,
|
||||
useTextSelectionTheme: false,
|
||||
);
|
||||
@ -377,7 +376,6 @@ void main() {
|
||||
elevatedButtonTheme: const ElevatedButtonThemeData(),
|
||||
outlinedButtonTheme: const OutlinedButtonThemeData(),
|
||||
textSelectionTheme: const TextSelectionThemeData(cursorColor: Colors.white),
|
||||
dataTableTheme: const DataTableThemeData(),
|
||||
fixTextFieldOutlineLabel: true,
|
||||
useTextSelectionTheme: true,
|
||||
);
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user