Header for PaginatedDataTable (#4468)
Also renames ButtonTheme.footer to ButtonTheme.bar.
This commit is contained in:
parent
1fe57277cf
commit
f75fd5c389
@ -96,7 +96,7 @@ class TravelDestinationItem extends StatelessWidget {
|
|||||||
),
|
),
|
||||||
// share, explore buttons
|
// share, explore buttons
|
||||||
// TODO(abarth): The theme and the bar should be part of card.
|
// TODO(abarth): The theme and the bar should be part of card.
|
||||||
new ButtonTheme.footer(
|
new ButtonTheme.bar(
|
||||||
child: new ButtonBar(
|
child: new ButtonBar(
|
||||||
alignment: MainAxisAlignment.start,
|
alignment: MainAxisAlignment.start,
|
||||||
children: <Widget>[
|
children: <Widget>[
|
||||||
|
@ -91,6 +91,8 @@ class DesertDataSource extends DataTableSource {
|
|||||||
notifyListeners();
|
notifyListeners();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int _selectedCount = 0;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
DataRow getRow(int index) {
|
DataRow getRow(int index) {
|
||||||
assert(index >= 0);
|
assert(index >= 0);
|
||||||
@ -101,8 +103,12 @@ class DesertDataSource extends DataTableSource {
|
|||||||
index: index,
|
index: index,
|
||||||
selected: desert.selected,
|
selected: desert.selected,
|
||||||
onSelectChanged: (bool value) {
|
onSelectChanged: (bool value) {
|
||||||
desert.selected = value;
|
if (desert.selected != value) {
|
||||||
notifyListeners();
|
_selectedCount += value ? 1 : -1;
|
||||||
|
assert(_selectedCount >= 0);
|
||||||
|
desert.selected = value;
|
||||||
|
notifyListeners();
|
||||||
|
}
|
||||||
},
|
},
|
||||||
cells: <DataCell>[
|
cells: <DataCell>[
|
||||||
new DataCell(new Text('${desert.name}')),
|
new DataCell(new Text('${desert.name}')),
|
||||||
@ -122,6 +128,16 @@ class DesertDataSource extends DataTableSource {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
bool get isRowCountApproximate => false;
|
bool get isRowCountApproximate => false;
|
||||||
|
|
||||||
|
@override
|
||||||
|
int get selectedRowCount => _selectedCount;
|
||||||
|
|
||||||
|
void _selectAll(bool checked) {
|
||||||
|
for (Desert desert in _deserts)
|
||||||
|
desert.selected = checked;
|
||||||
|
_selectedCount = checked ? _deserts.length : 0;
|
||||||
|
notifyListeners();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class DataTableDemo extends StatefulWidget {
|
class DataTableDemo extends StatefulWidget {
|
||||||
@ -135,10 +151,10 @@ class _DataTableDemoState extends State<DataTableDemo> {
|
|||||||
int _rowsPerPage = PaginatedDataTable.defaultRowsPerPage;
|
int _rowsPerPage = PaginatedDataTable.defaultRowsPerPage;
|
||||||
int _sortColumnIndex;
|
int _sortColumnIndex;
|
||||||
bool _sortAscending = true;
|
bool _sortAscending = true;
|
||||||
DesertDataSource _deserts = new DesertDataSource();
|
DesertDataSource _desertsDataSource = new DesertDataSource();
|
||||||
|
|
||||||
void _sort/*<T>*/(Comparable<dynamic/*=T*/> getField(Desert d), int columnIndex, bool ascending) {
|
void _sort/*<T>*/(Comparable<dynamic/*=T*/> getField(Desert d), int columnIndex, bool ascending) {
|
||||||
_deserts._sort/*<T>*/(getField, ascending);
|
_desertsDataSource._sort/*<T>*/(getField, ascending);
|
||||||
setState(() {
|
setState(() {
|
||||||
_sortColumnIndex = columnIndex;
|
_sortColumnIndex = columnIndex;
|
||||||
_sortAscending = ascending;
|
_sortAscending = ascending;
|
||||||
@ -153,10 +169,12 @@ class _DataTableDemoState extends State<DataTableDemo> {
|
|||||||
padding: const EdgeInsets.all(20.0),
|
padding: const EdgeInsets.all(20.0),
|
||||||
children: <Widget>[
|
children: <Widget>[
|
||||||
new PaginatedDataTable(
|
new PaginatedDataTable(
|
||||||
|
header: new Text('Nutrition'),
|
||||||
rowsPerPage: _rowsPerPage,
|
rowsPerPage: _rowsPerPage,
|
||||||
onRowsPerPageChanged: (int value) { setState(() { _rowsPerPage = value; }); },
|
onRowsPerPageChanged: (int value) { setState(() { _rowsPerPage = value; }); },
|
||||||
sortColumnIndex: _sortColumnIndex,
|
sortColumnIndex: _sortColumnIndex,
|
||||||
sortAscending: _sortAscending,
|
sortAscending: _sortAscending,
|
||||||
|
onSelectAll: _desertsDataSource._selectAll,
|
||||||
columns: <DataColumn>[
|
columns: <DataColumn>[
|
||||||
new DataColumn(
|
new DataColumn(
|
||||||
label: new Text('Dessert (100g serving)'),
|
label: new Text('Dessert (100g serving)'),
|
||||||
@ -200,7 +218,7 @@ class _DataTableDemoState extends State<DataTableDemo> {
|
|||||||
onSort: (int columnIndex, bool ascending) => _sort/*<num>*/((Desert d) => d.iron, columnIndex, ascending)
|
onSort: (int columnIndex, bool ascending) => _sort/*<num>*/((Desert d) => d.iron, columnIndex, ascending)
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
source: _deserts
|
source: _desertsDataSource
|
||||||
)
|
)
|
||||||
]
|
]
|
||||||
)
|
)
|
||||||
|
@ -50,15 +50,21 @@ class ButtonTheme extends InheritedWidget {
|
|||||||
Widget child
|
Widget child
|
||||||
}) : super(key: key, child: child);
|
}) : super(key: key, child: child);
|
||||||
|
|
||||||
/// Creates a button theme that is appropriate for footer buttons.
|
/// Creates a button theme that is appropriate for button bars, as used in
|
||||||
|
/// dialog footers and in the headers of data tables.
|
||||||
///
|
///
|
||||||
/// This theme is denser, with a smaller [minWidth] and [padding], than the
|
/// This theme is denser, with a smaller [minWidth] and [padding], than the
|
||||||
/// default theme. Also, this theme uses [ButtonTextTheme.accent] rather than
|
/// default theme. Also, this theme uses [ButtonTextTheme.accent] rather than
|
||||||
/// [ButtonTextTheme.normal].
|
/// [ButtonTextTheme.normal].
|
||||||
///
|
///
|
||||||
|
/// For best effect, the label of the button at the edge of the container
|
||||||
|
/// should have text that ends up wider than 64.0 pixels. This ensures that
|
||||||
|
/// the alignment of the text matches the alignment of the edge of the
|
||||||
|
/// container.
|
||||||
|
///
|
||||||
/// For example, buttons at the bottom of [Dialog] or [Card] widgets use this
|
/// For example, buttons at the bottom of [Dialog] or [Card] widgets use this
|
||||||
/// button theme.
|
/// button theme.
|
||||||
const ButtonTheme.footer({
|
const ButtonTheme.bar({
|
||||||
Key key,
|
Key key,
|
||||||
this.textTheme: ButtonTextTheme.accent,
|
this.textTheme: ButtonTextTheme.accent,
|
||||||
this.minWidth: 64.0,
|
this.minWidth: 64.0,
|
||||||
|
@ -51,7 +51,7 @@ class ButtonBar extends StatelessWidget {
|
|||||||
),
|
),
|
||||||
child: new Row(
|
child: new Row(
|
||||||
mainAxisAlignment: alignment,
|
mainAxisAlignment: alignment,
|
||||||
children: children.map((Widget child) {
|
children: children.map/*<Widget>*/((Widget child) {
|
||||||
return new Padding(
|
return new Padding(
|
||||||
padding: new EdgeInsets.symmetric(horizontal: paddingUnit),
|
padding: new EdgeInsets.symmetric(horizontal: paddingUnit),
|
||||||
child: child
|
child: child
|
||||||
|
@ -54,4 +54,9 @@ abstract class DataTableSource extends ChangeNotifier {
|
|||||||
/// then later the exact number becomes available, then call
|
/// then later the exact number becomes available, then call
|
||||||
/// [notifyListeners].
|
/// [notifyListeners].
|
||||||
bool get isRowCountApproximate;
|
bool get isRowCountApproximate;
|
||||||
|
|
||||||
|
/// Called to obtain the number of rows that are currently selected.
|
||||||
|
///
|
||||||
|
/// If the selected row count changes, call [notifyListeners].
|
||||||
|
int get selectedRowCount;
|
||||||
}
|
}
|
@ -96,7 +96,7 @@ class Dialog extends StatelessWidget {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (actions != null) {
|
if (actions != null) {
|
||||||
dialogBody.add(new ButtonTheme.footer(
|
dialogBody.add(new ButtonTheme.bar(
|
||||||
child: new ButtonBar(
|
child: new ButtonBar(
|
||||||
alignment: MainAxisAlignment.end,
|
alignment: MainAxisAlignment.end,
|
||||||
children: actions
|
children: actions
|
||||||
|
@ -4,9 +4,12 @@
|
|||||||
|
|
||||||
import 'dart:math' as math;
|
import 'dart:math' as math;
|
||||||
|
|
||||||
|
import 'package:meta/meta.dart';
|
||||||
import 'package:flutter/widgets.dart';
|
import 'package:flutter/widgets.dart';
|
||||||
import 'package:flutter/rendering.dart';
|
import 'package:flutter/rendering.dart';
|
||||||
|
|
||||||
|
import 'button.dart';
|
||||||
|
import 'button_bar.dart';
|
||||||
import 'card.dart';
|
import 'card.dart';
|
||||||
import 'data_table.dart';
|
import 'data_table.dart';
|
||||||
import 'data_table_source.dart';
|
import 'data_table_source.dart';
|
||||||
@ -23,6 +26,9 @@ import 'theme.dart';
|
|||||||
class PaginatedDataTable extends StatefulWidget {
|
class PaginatedDataTable extends StatefulWidget {
|
||||||
/// Creates a widget describing a paginated [DataTable] on a [Card].
|
/// Creates a widget describing a paginated [DataTable] on a [Card].
|
||||||
///
|
///
|
||||||
|
/// The [header] should give the card's header, typically a [Text] widget. It
|
||||||
|
/// must not be null.
|
||||||
|
///
|
||||||
/// The [columns] argument must be a list of as many [DataColumn] objects as
|
/// The [columns] argument must be a list of as many [DataColumn] objects as
|
||||||
/// the table is to have columns, ignoring the leading checkbox column if any.
|
/// the table is to have columns, ignoring the leading checkbox column if any.
|
||||||
/// The [columns] argument must have a length greater than zero and cannot be
|
/// The [columns] argument must have a length greater than zero and cannot be
|
||||||
@ -43,10 +49,12 @@ class PaginatedDataTable extends StatefulWidget {
|
|||||||
/// widget unless the data table really is to now show entirely different
|
/// widget unless the data table really is to now show entirely different
|
||||||
/// data from a new source.
|
/// data from a new source.
|
||||||
///
|
///
|
||||||
/// The [rowsPerPage] and [availableRowsPerPage] must not be null (though they
|
/// The [rowsPerPage] and [availableRowsPerPage] must not be null (they
|
||||||
/// both have defaults, so don't have to be specified).
|
/// both have defaults, though, so don't have to be specified).
|
||||||
PaginatedDataTable({
|
PaginatedDataTable({
|
||||||
Key key,
|
Key key,
|
||||||
|
@required this.header,
|
||||||
|
this.actions,
|
||||||
this.columns,
|
this.columns,
|
||||||
this.sortColumnIndex,
|
this.sortColumnIndex,
|
||||||
this.sortAscending: true,
|
this.sortAscending: true,
|
||||||
@ -56,8 +64,9 @@ class PaginatedDataTable extends StatefulWidget {
|
|||||||
this.rowsPerPage: defaultRowsPerPage,
|
this.rowsPerPage: defaultRowsPerPage,
|
||||||
this.availableRowsPerPage: const <int>[defaultRowsPerPage, defaultRowsPerPage * 2, defaultRowsPerPage * 5, defaultRowsPerPage * 10],
|
this.availableRowsPerPage: const <int>[defaultRowsPerPage, defaultRowsPerPage * 2, defaultRowsPerPage * 5, defaultRowsPerPage * 10],
|
||||||
this.onRowsPerPageChanged,
|
this.onRowsPerPageChanged,
|
||||||
this.source
|
@required this.source
|
||||||
}) : super(key: key) {
|
}) : super(key: key) {
|
||||||
|
assert(header != null);
|
||||||
assert(columns != null);
|
assert(columns != null);
|
||||||
assert(columns.length > 0);
|
assert(columns.length > 0);
|
||||||
assert(sortColumnIndex == null || (sortColumnIndex >= 0 && sortColumnIndex < columns.length));
|
assert(sortColumnIndex == null || (sortColumnIndex >= 0 && sortColumnIndex < columns.length));
|
||||||
@ -69,6 +78,24 @@ class PaginatedDataTable extends StatefulWidget {
|
|||||||
assert(source != null);
|
assert(source != null);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// The table card's header.
|
||||||
|
///
|
||||||
|
/// This is typically a [Text] widget, but can also be a [ButtonBar] with
|
||||||
|
/// [FlatButton]s. Suitable defaults are automatically provided for the font,
|
||||||
|
/// button color, button padding, and so forth.
|
||||||
|
///
|
||||||
|
/// If items in the table are selectable, then, when the selection is not
|
||||||
|
/// empty, the header is replaced by a count of the selected items.
|
||||||
|
final Widget header;
|
||||||
|
|
||||||
|
/// Icon buttons to show at the top right of the table.
|
||||||
|
///
|
||||||
|
/// Typically, the exact actions included in this list will vary based on
|
||||||
|
/// whether any rows are selected or not.
|
||||||
|
///
|
||||||
|
/// These should be size 24.0 with default padding (8.0).
|
||||||
|
final List<Widget> actions;
|
||||||
|
|
||||||
/// The configuration and labels for the columns in the table.
|
/// The configuration and labels for the columns in the table.
|
||||||
final List<DataColumn> columns;
|
final List<DataColumn> columns;
|
||||||
|
|
||||||
@ -142,6 +169,7 @@ class PaginatedDataTableState extends State<PaginatedDataTable> {
|
|||||||
int _firstRowIndex;
|
int _firstRowIndex;
|
||||||
int _rowCount;
|
int _rowCount;
|
||||||
bool _rowCountApproximate;
|
bool _rowCountApproximate;
|
||||||
|
int _selectedRowCount;
|
||||||
final Map<int, DataRow> _rows = <int, DataRow>{};
|
final Map<int, DataRow> _rows = <int, DataRow>{};
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@ -172,6 +200,7 @@ class PaginatedDataTableState extends State<PaginatedDataTable> {
|
|||||||
setState(() {
|
setState(() {
|
||||||
_rowCount = config.source.rowCount;
|
_rowCount = config.source.rowCount;
|
||||||
_rowCountApproximate = config.source.isRowCountApproximate;
|
_rowCountApproximate = config.source.isRowCountApproximate;
|
||||||
|
_selectedRowCount = config.source.selectedRowCount;
|
||||||
_rows.clear();
|
_rows.clear();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -237,7 +266,42 @@ class PaginatedDataTableState extends State<PaginatedDataTable> {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
final TextStyle textStyle = Theme.of(context).textTheme.caption;
|
// TODO(ianh): This whole build function doesn't handle RTL yet.
|
||||||
|
ThemeData themeData = Theme.of(context);
|
||||||
|
// HEADER
|
||||||
|
final List<Widget> headerWidgets = <Widget>[];
|
||||||
|
double leftPadding = 24.0;
|
||||||
|
if (_selectedRowCount == 0) {
|
||||||
|
headerWidgets.add(new Flexible(child: config.header));
|
||||||
|
if (config.header is ButtonBar) {
|
||||||
|
// We adjust the padding when a button bar is present, because the
|
||||||
|
// ButtonBar introduces 2 pixels of outside padding, plus 2 pixels
|
||||||
|
// around each button on each side, and the button itself will have 8
|
||||||
|
// pixels internally on each side, yet we want the left edge of the
|
||||||
|
// inside of the button to line up with the 24.0 left inset.
|
||||||
|
// TODO(ianh): Better magic. See https://github.com/flutter/flutter/issues/4460
|
||||||
|
leftPadding = 12.0;
|
||||||
|
}
|
||||||
|
} else if (_selectedRowCount == 1) {
|
||||||
|
// TODO(ianh): Real l10n.
|
||||||
|
headerWidgets.add(new Flexible(child: new Text('1 item selected')));
|
||||||
|
} else {
|
||||||
|
headerWidgets.add(new Flexible(child: new Text('$_selectedRowCount items selected')));
|
||||||
|
}
|
||||||
|
if (config.actions != null) {
|
||||||
|
headerWidgets.addAll(
|
||||||
|
config.actions.map/*<Widget>*/((Widget widget) {
|
||||||
|
return new Padding(
|
||||||
|
// 8.0 is the default padding of an icon button
|
||||||
|
padding: new EdgeInsets.only(left: 24.0 - 8.0 * 2.0),
|
||||||
|
child: widget
|
||||||
|
);
|
||||||
|
}).toList()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// FOOTER
|
||||||
|
final TextStyle footerTextStyle = themeData.textTheme.caption;
|
||||||
final List<Widget> footerWidgets = <Widget>[];
|
final List<Widget> footerWidgets = <Widget>[];
|
||||||
if (config.onRowsPerPageChanged != null) {
|
if (config.onRowsPerPageChanged != null) {
|
||||||
List<Widget> availableRowsPerPage = config.availableRowsPerPage
|
List<Widget> availableRowsPerPage = config.availableRowsPerPage
|
||||||
@ -256,7 +320,7 @@ class PaginatedDataTableState extends State<PaginatedDataTable> {
|
|||||||
items: availableRowsPerPage,
|
items: availableRowsPerPage,
|
||||||
value: config.rowsPerPage,
|
value: config.rowsPerPage,
|
||||||
onChanged: config.onRowsPerPageChanged,
|
onChanged: config.onRowsPerPageChanged,
|
||||||
style: textStyle,
|
style: footerTextStyle,
|
||||||
iconSize: 24.0
|
iconSize: 24.0
|
||||||
)
|
)
|
||||||
),
|
),
|
||||||
@ -285,21 +349,39 @@ class PaginatedDataTableState extends State<PaginatedDataTable> {
|
|||||||
),
|
),
|
||||||
new Container(width: 14.0),
|
new Container(width: 14.0),
|
||||||
]);
|
]);
|
||||||
|
|
||||||
|
// CARD
|
||||||
return new Card(
|
return new Card(
|
||||||
// TODO(ianh): data table card headers
|
|
||||||
/*
|
|
||||||
- title, top left
|
|
||||||
- 20px Roboto Regular, black87
|
|
||||||
- persistent actions, top left
|
|
||||||
- header when there's a selection
|
|
||||||
- accent 50?
|
|
||||||
- show number of selected items
|
|
||||||
- different actions
|
|
||||||
- actions, top right
|
|
||||||
- 24px icons, black54
|
|
||||||
*/
|
|
||||||
child: new BlockBody(
|
child: new BlockBody(
|
||||||
children: <Widget>[
|
children: <Widget>[
|
||||||
|
new DefaultTextStyle(
|
||||||
|
// These typographic styles aren't quite the regular ones. We pick the closest ones from the regular
|
||||||
|
// list and then tweak them appropriately.
|
||||||
|
// See https://www.google.com/design/spec/components/data-tables.html#data-tables-tables-within-cards
|
||||||
|
style: _selectedRowCount > 0 ? themeData.textTheme.subhead.copyWith(color: themeData.accentColor)
|
||||||
|
: themeData.textTheme.title.copyWith(fontWeight: FontWeight.w400),
|
||||||
|
child: new IconTheme(
|
||||||
|
data: new IconThemeData(
|
||||||
|
opacity: 0.54
|
||||||
|
),
|
||||||
|
child: new ButtonTheme.bar(
|
||||||
|
child: new Container(
|
||||||
|
height: 64.0,
|
||||||
|
padding: new EdgeInsets.fromLTRB(leftPadding, 0.0, 14.0, 0.0),
|
||||||
|
// TODO(ianh): This decoration will prevent ink splashes from being visible.
|
||||||
|
// Instead, we should have a widget that prints the decoration on the material.
|
||||||
|
// See https://github.com/flutter/flutter/issues/3782
|
||||||
|
decoration: _selectedRowCount > 0 ? new BoxDecoration(
|
||||||
|
backgroundColor: themeData.secondaryHeaderColor
|
||||||
|
) : null,
|
||||||
|
child: new Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.end,
|
||||||
|
children: headerWidgets
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
),
|
||||||
new ScrollableViewport(
|
new ScrollableViewport(
|
||||||
scrollDirection: Axis.horizontal,
|
scrollDirection: Axis.horizontal,
|
||||||
child: new DataTable(
|
child: new DataTable(
|
||||||
@ -312,7 +394,7 @@ class PaginatedDataTableState extends State<PaginatedDataTable> {
|
|||||||
)
|
)
|
||||||
),
|
),
|
||||||
new DefaultTextStyle(
|
new DefaultTextStyle(
|
||||||
style: textStyle,
|
style: footerTextStyle,
|
||||||
child: new IconTheme(
|
child: new IconTheme(
|
||||||
data: new IconThemeData(
|
data: new IconThemeData(
|
||||||
opacity: 0.54
|
opacity: 0.54
|
||||||
|
@ -67,6 +67,7 @@ class ThemeData {
|
|||||||
Color unselectedWidgetColor,
|
Color unselectedWidgetColor,
|
||||||
Color disabledColor,
|
Color disabledColor,
|
||||||
Color buttonColor,
|
Color buttonColor,
|
||||||
|
Color secondaryHeaderColor,
|
||||||
Color textSelectionColor,
|
Color textSelectionColor,
|
||||||
Color textSelectionHandleColor,
|
Color textSelectionHandleColor,
|
||||||
Color backgroundColor,
|
Color backgroundColor,
|
||||||
@ -93,6 +94,7 @@ class ThemeData {
|
|||||||
unselectedWidgetColor ??= isDark ? Colors.white70 : Colors.black54;
|
unselectedWidgetColor ??= isDark ? Colors.white70 : Colors.black54;
|
||||||
disabledColor ??= isDark ? Colors.white30 : Colors.black26;
|
disabledColor ??= isDark ? Colors.white30 : Colors.black26;
|
||||||
buttonColor ??= isDark ? primarySwatch[600] : Colors.grey[300];
|
buttonColor ??= isDark ? primarySwatch[600] : Colors.grey[300];
|
||||||
|
secondaryHeaderColor ??= primarySwatch[50]; // TODO(ianh): dark theme support (https://github.com/flutter/flutter/issues/3370)
|
||||||
textSelectionColor ??= isDark ? accentColor : primarySwatch[200];
|
textSelectionColor ??= isDark ? accentColor : primarySwatch[200];
|
||||||
textSelectionHandleColor ??= isDark ? Colors.tealAccent[400] : primarySwatch[300];
|
textSelectionHandleColor ??= isDark ? Colors.tealAccent[400] : primarySwatch[300];
|
||||||
backgroundColor ??= isDark ? Colors.grey[700] : primarySwatch[200];
|
backgroundColor ??= isDark ? Colors.grey[700] : primarySwatch[200];
|
||||||
@ -117,6 +119,7 @@ class ThemeData {
|
|||||||
unselectedWidgetColor: unselectedWidgetColor,
|
unselectedWidgetColor: unselectedWidgetColor,
|
||||||
disabledColor: disabledColor,
|
disabledColor: disabledColor,
|
||||||
buttonColor: buttonColor,
|
buttonColor: buttonColor,
|
||||||
|
secondaryHeaderColor: secondaryHeaderColor,
|
||||||
textSelectionColor: textSelectionColor,
|
textSelectionColor: textSelectionColor,
|
||||||
textSelectionHandleColor: textSelectionHandleColor,
|
textSelectionHandleColor: textSelectionHandleColor,
|
||||||
backgroundColor: backgroundColor,
|
backgroundColor: backgroundColor,
|
||||||
@ -150,6 +153,7 @@ class ThemeData {
|
|||||||
this.unselectedWidgetColor,
|
this.unselectedWidgetColor,
|
||||||
this.disabledColor,
|
this.disabledColor,
|
||||||
this.buttonColor,
|
this.buttonColor,
|
||||||
|
this.secondaryHeaderColor,
|
||||||
this.textSelectionColor,
|
this.textSelectionColor,
|
||||||
this.textSelectionHandleColor,
|
this.textSelectionHandleColor,
|
||||||
this.backgroundColor,
|
this.backgroundColor,
|
||||||
@ -174,6 +178,7 @@ class ThemeData {
|
|||||||
assert(unselectedWidgetColor != null);
|
assert(unselectedWidgetColor != null);
|
||||||
assert(disabledColor != null);
|
assert(disabledColor != null);
|
||||||
assert(buttonColor != null);
|
assert(buttonColor != null);
|
||||||
|
assert(secondaryHeaderColor != null);
|
||||||
assert(textSelectionColor != null);
|
assert(textSelectionColor != null);
|
||||||
assert(textSelectionHandleColor != null);
|
assert(textSelectionHandleColor != null);
|
||||||
assert(disabledColor != null);
|
assert(disabledColor != null);
|
||||||
@ -257,6 +262,12 @@ class ThemeData {
|
|||||||
/// The default color of the [Material] used in [RaisedButton]s.
|
/// The default color of the [Material] used in [RaisedButton]s.
|
||||||
final Color buttonColor;
|
final Color buttonColor;
|
||||||
|
|
||||||
|
/// The color of the header of a [PaginatedDataTable] when there are selected rows.
|
||||||
|
// According to the spec for data tables:
|
||||||
|
// https://material.google.com/components/data-tables.html#data-tables-tables-within-cards
|
||||||
|
// ...this should be the "50-value of secondary app color".
|
||||||
|
final Color secondaryHeaderColor;
|
||||||
|
|
||||||
/// The color of text selections in text fields, such as [Input].
|
/// The color of text selections in text fields, such as [Input].
|
||||||
final Color textSelectionColor;
|
final Color textSelectionColor;
|
||||||
|
|
||||||
@ -301,6 +312,7 @@ class ThemeData {
|
|||||||
unselectedWidgetColor: Color.lerp(begin.unselectedWidgetColor, end.unselectedWidgetColor, t),
|
unselectedWidgetColor: Color.lerp(begin.unselectedWidgetColor, end.unselectedWidgetColor, t),
|
||||||
disabledColor: Color.lerp(begin.disabledColor, end.disabledColor, t),
|
disabledColor: Color.lerp(begin.disabledColor, end.disabledColor, t),
|
||||||
buttonColor: Color.lerp(begin.buttonColor, end.buttonColor, t),
|
buttonColor: Color.lerp(begin.buttonColor, end.buttonColor, t),
|
||||||
|
secondaryHeaderColor: Color.lerp(begin.secondaryHeaderColor, end.secondaryHeaderColor, t),
|
||||||
textSelectionColor: Color.lerp(begin.textSelectionColor, end.textSelectionColor, t),
|
textSelectionColor: Color.lerp(begin.textSelectionColor, end.textSelectionColor, t),
|
||||||
textSelectionHandleColor: Color.lerp(begin.textSelectionHandleColor, end.textSelectionHandleColor, t),
|
textSelectionHandleColor: Color.lerp(begin.textSelectionHandleColor, end.textSelectionHandleColor, t),
|
||||||
backgroundColor: Color.lerp(begin.backgroundColor, end.backgroundColor, t),
|
backgroundColor: Color.lerp(begin.backgroundColor, end.backgroundColor, t),
|
||||||
@ -332,6 +344,7 @@ class ThemeData {
|
|||||||
(otherData.unselectedWidgetColor == unselectedWidgetColor) &&
|
(otherData.unselectedWidgetColor == unselectedWidgetColor) &&
|
||||||
(otherData.disabledColor == disabledColor) &&
|
(otherData.disabledColor == disabledColor) &&
|
||||||
(otherData.buttonColor == buttonColor) &&
|
(otherData.buttonColor == buttonColor) &&
|
||||||
|
(otherData.secondaryHeaderColor == secondaryHeaderColor) &&
|
||||||
(otherData.textSelectionColor == textSelectionColor) &&
|
(otherData.textSelectionColor == textSelectionColor) &&
|
||||||
(otherData.textSelectionHandleColor == textSelectionHandleColor) &&
|
(otherData.textSelectionHandleColor == textSelectionHandleColor) &&
|
||||||
(otherData.backgroundColor == backgroundColor) &&
|
(otherData.backgroundColor == backgroundColor) &&
|
||||||
@ -360,12 +373,13 @@ class ThemeData {
|
|||||||
unselectedWidgetColor,
|
unselectedWidgetColor,
|
||||||
disabledColor,
|
disabledColor,
|
||||||
buttonColor,
|
buttonColor,
|
||||||
|
secondaryHeaderColor,
|
||||||
textSelectionColor,
|
textSelectionColor,
|
||||||
textSelectionHandleColor,
|
textSelectionHandleColor,
|
||||||
backgroundColor,
|
backgroundColor,
|
||||||
accentColor,
|
accentColor,
|
||||||
|
accentColorBrightness,
|
||||||
hashValues( // Too many values.
|
hashValues( // Too many values.
|
||||||
accentColorBrightness,
|
|
||||||
indicatorColor,
|
indicatorColor,
|
||||||
hintColor,
|
hintColor,
|
||||||
errorColor,
|
errorColor,
|
||||||
|
Loading…
x
Reference in New Issue
Block a user