Update ListTile
text defaults to use ColorScheme
(#128581)
fixes https://github.com/flutter/flutter/issues/128569 <details> <summary>code sample</summary> ```dart import 'package:flutter/material.dart'; void main() { runApp(const ListTileApp()); } class ListTileApp extends StatelessWidget { const ListTileApp({super.key}); @override Widget build(BuildContext context) { return MaterialApp( title: 'Flutter Demo', theme: ThemeData( useMaterial3: true, colorScheme: ColorScheme.fromSeed(seedColor: Colors.red).copyWith( onSurface: Colors.yellow, onSurfaceVariant: Colors.green, ), ), home: const Scaffold( body: Center( child: ListTile( title: Text('title'), subtitle: Text('subtitle'), ), ), ), ); } } ``` </details> # Description M3 ListTile couldn't be customized using `ColorScheme` colors. - This PR updates the list tile text defaults to `ColorScheme` text color tokens. - Improved the `ListTile` template to use the token group. - Update docs and tests. ```dart colorScheme: ColorScheme.fromSeed(seedColor: Colors.red).copyWith( onSurface: Colors.yellow, onSurfaceVariant: Colors.green, ), ``` ### Before  ### After 
This commit is contained in:
parent
6f2118be77
commit
ca5aa2329a
@ -397,8 +397,10 @@ md.comp.list.list-item.pressed.leading-icon.icon.color,
|
|||||||
md.comp.list.list-item.pressed.state-layer.color,
|
md.comp.list.list-item.pressed.state-layer.color,
|
||||||
md.comp.list.list-item.pressed.state-layer.opacity,
|
md.comp.list.list-item.pressed.state-layer.opacity,
|
||||||
md.comp.list.list-item.selected.trailing-icon.color,
|
md.comp.list.list-item.selected.trailing-icon.color,
|
||||||
|
md.comp.list.list-item.supporting-text.color,
|
||||||
md.comp.list.list-item.supporting-text.text-style,
|
md.comp.list.list-item.supporting-text.text-style,
|
||||||
md.comp.list.list-item.trailing-icon.color,
|
md.comp.list.list-item.trailing-icon.color,
|
||||||
|
md.comp.list.list-item.trailing-supporting-text.color,
|
||||||
md.comp.list.list-item.trailing-supporting-text.text-style,
|
md.comp.list.list-item.trailing-supporting-text.text-style,
|
||||||
md.comp.menu.container.color,
|
md.comp.menu.container.color,
|
||||||
md.comp.menu.container.elevation,
|
md.comp.menu.container.elevation,
|
||||||
|
|
@ -10,6 +10,8 @@ class ListTileTemplate extends TokenTemplate {
|
|||||||
super.textThemePrefix = '_textTheme.',
|
super.textThemePrefix = '_textTheme.',
|
||||||
});
|
});
|
||||||
|
|
||||||
|
static const String tokenGroup = 'md.comp.list.list-item';
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String generate() => '''
|
String generate() => '''
|
||||||
class _${blockName}DefaultsM3 extends ListTileThemeData {
|
class _${blockName}DefaultsM3 extends ListTileThemeData {
|
||||||
@ -18,7 +20,7 @@ class _${blockName}DefaultsM3 extends ListTileThemeData {
|
|||||||
contentPadding: const EdgeInsetsDirectional.only(start: 16.0, end: 24.0),
|
contentPadding: const EdgeInsetsDirectional.only(start: 16.0, end: 24.0),
|
||||||
minLeadingWidth: 24,
|
minLeadingWidth: 24,
|
||||||
minVerticalPadding: 8,
|
minVerticalPadding: 8,
|
||||||
shape: ${shape("md.comp.list.list-item.container")},
|
shape: ${shape("$tokenGroup.container")},
|
||||||
);
|
);
|
||||||
|
|
||||||
final BuildContext context;
|
final BuildContext context;
|
||||||
@ -30,19 +32,19 @@ class _${blockName}DefaultsM3 extends ListTileThemeData {
|
|||||||
Color? get tileColor => Colors.transparent;
|
Color? get tileColor => Colors.transparent;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
TextStyle? get titleTextStyle => ${textStyle("md.comp.list.list-item.label-text")};
|
TextStyle? get titleTextStyle => ${textStyle("$tokenGroup.label-text")}!.copyWith(color: ${componentColor('$tokenGroup.label-text')});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
TextStyle? get subtitleTextStyle => ${textStyle("md.comp.list.list-item.supporting-text")};
|
TextStyle? get subtitleTextStyle => ${textStyle("$tokenGroup.supporting-text")}!.copyWith(color: ${componentColor('$tokenGroup.supporting-text')});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
TextStyle? get leadingAndTrailingTextStyle => ${textStyle("md.comp.list.list-item.trailing-supporting-text")};
|
TextStyle? get leadingAndTrailingTextStyle => ${textStyle("$tokenGroup.trailing-supporting-text")}!.copyWith(color: ${componentColor('$tokenGroup.trailing-supporting-text')});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Color? get selectedColor => ${componentColor('md.comp.list.list-item.selected.trailing-icon')};
|
Color? get selectedColor => ${componentColor('$tokenGroup.selected.trailing-icon')};
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Color? get iconColor => ${componentColor('md.comp.list.list-item.trailing-icon')};
|
Color? get iconColor => ${componentColor('$tokenGroup.trailing-icon')};
|
||||||
}
|
}
|
||||||
''';
|
''';
|
||||||
}
|
}
|
||||||
|
@ -509,22 +509,25 @@ class ListTile extends StatelessWidget {
|
|||||||
///
|
///
|
||||||
/// If this property is null, then [ListTileThemeData.titleTextStyle] is used.
|
/// If this property is null, then [ListTileThemeData.titleTextStyle] is used.
|
||||||
/// If that is also null and [ThemeData.useMaterial3] is true, [TextTheme.bodyLarge]
|
/// If that is also null and [ThemeData.useMaterial3] is true, [TextTheme.bodyLarge]
|
||||||
/// will be used. Otherwise, If ListTile style is [ListTileStyle.list],
|
/// with [ColorScheme.onSurface] will be used. Otherwise, If ListTile style is
|
||||||
/// [TextTheme.titleMedium] will be used and if ListTile style is [ListTileStyle.drawer],
|
/// [ListTileStyle.list], [TextTheme.titleMedium] will be used and if ListTile style
|
||||||
/// [TextTheme.bodyLarge] will be used.
|
/// is [ListTileStyle.drawer], [TextTheme.bodyLarge] will be used.
|
||||||
final TextStyle? titleTextStyle;
|
final TextStyle? titleTextStyle;
|
||||||
|
|
||||||
/// The text style for ListTile's [subtitle].
|
/// The text style for ListTile's [subtitle].
|
||||||
///
|
///
|
||||||
/// If this property is null, then [ListTileThemeData.subtitleTextStyle] is used.
|
/// If this property is null, then [ListTileThemeData.subtitleTextStyle] is used.
|
||||||
/// If that is also null, [TextTheme.bodyMedium] will be used.
|
/// If that is also null and [ThemeData.useMaterial3] is true, [TextTheme.bodyMedium]
|
||||||
|
/// with [ColorScheme.onSurfaceVariant] will be used, otherwise [TextTheme.bodyMedium]
|
||||||
|
/// with [TextTheme.bodySmall] color will be used.
|
||||||
final TextStyle? subtitleTextStyle;
|
final TextStyle? subtitleTextStyle;
|
||||||
|
|
||||||
/// The text style for ListTile's [leading] and [trailing].
|
/// The text style for ListTile's [leading] and [trailing].
|
||||||
///
|
///
|
||||||
/// If this property is null, then [ListTileThemeData.leadingAndTrailingTextStyle] is used.
|
/// If this property is null, then [ListTileThemeData.leadingAndTrailingTextStyle] is used.
|
||||||
/// If that is also null and [ThemeData.useMaterial3] is true, [TextTheme.labelSmall]
|
/// If that is also null and [ThemeData.useMaterial3] is true, [TextTheme.labelSmall]
|
||||||
/// will be used, otherwise [TextTheme.bodyMedium] will be used.
|
/// with [ColorScheme.onSurfaceVariant] will be used, otherwise [TextTheme.bodyMedium]
|
||||||
|
/// will be used.
|
||||||
final TextStyle? leadingAndTrailingTextStyle;
|
final TextStyle? leadingAndTrailingTextStyle;
|
||||||
|
|
||||||
/// Defines the font used for the [title].
|
/// Defines the font used for the [title].
|
||||||
@ -798,7 +801,8 @@ class ListTile extends StatelessWidget {
|
|||||||
subtitleStyle = subtitleTextStyle
|
subtitleStyle = subtitleTextStyle
|
||||||
?? tileTheme.subtitleTextStyle
|
?? tileTheme.subtitleTextStyle
|
||||||
?? defaults.subtitleTextStyle!;
|
?? defaults.subtitleTextStyle!;
|
||||||
final Color? subtitleColor = effectiveColor ?? theme.textTheme.bodySmall!.color;
|
final Color? subtitleColor = effectiveColor
|
||||||
|
?? (theme.useMaterial3 ? null : theme.textTheme.bodySmall!.color);
|
||||||
subtitleStyle = subtitleStyle.copyWith(
|
subtitleStyle = subtitleStyle.copyWith(
|
||||||
color: subtitleColor,
|
color: subtitleColor,
|
||||||
fontSize: _isDenseLayout(theme, tileTheme) ? 12.0 : null,
|
fontSize: _isDenseLayout(theme, tileTheme) ? 12.0 : null,
|
||||||
@ -1575,13 +1579,13 @@ class _LisTileDefaultsM3 extends ListTileThemeData {
|
|||||||
Color? get tileColor => Colors.transparent;
|
Color? get tileColor => Colors.transparent;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
TextStyle? get titleTextStyle => _textTheme.bodyLarge;
|
TextStyle? get titleTextStyle => _textTheme.bodyLarge!.copyWith(color: _colors.onSurface);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
TextStyle? get subtitleTextStyle => _textTheme.bodyMedium;
|
TextStyle? get subtitleTextStyle => _textTheme.bodyMedium!.copyWith(color: _colors.onSurfaceVariant);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
TextStyle? get leadingAndTrailingTextStyle => _textTheme.labelSmall;
|
TextStyle? get leadingAndTrailingTextStyle => _textTheme.labelSmall!.copyWith(color: _colors.onSurfaceVariant);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Color? get selectedColor => _colors.primary;
|
Color? get selectedColor => _colors.primary;
|
||||||
|
@ -1947,13 +1947,13 @@ void main() {
|
|||||||
// ListTile default text colors.
|
// ListTile default text colors.
|
||||||
await tester.pumpWidget(buildFrame());
|
await tester.pumpWidget(buildFrame());
|
||||||
final RenderParagraph leading = _getTextRenderObject(tester, 'leading');
|
final RenderParagraph leading = _getTextRenderObject(tester, 'leading');
|
||||||
expect(leading.text.style!.color, theme.textTheme.labelSmall!.color);
|
expect(leading.text.style!.color, theme.colorScheme.onSurfaceVariant);
|
||||||
final RenderParagraph title = _getTextRenderObject(tester, 'title');
|
final RenderParagraph title = _getTextRenderObject(tester, 'title');
|
||||||
expect(title.text.style!.color, theme.textTheme.bodyLarge!.color);
|
expect(title.text.style!.color, theme.colorScheme.onSurface);
|
||||||
final RenderParagraph subtitle = _getTextRenderObject(tester, 'subtitle');
|
final RenderParagraph subtitle = _getTextRenderObject(tester, 'subtitle');
|
||||||
expect(subtitle.text.style!.color, theme.textTheme.bodyMedium!.color);
|
expect(subtitle.text.style!.color, theme.colorScheme.onSurfaceVariant);
|
||||||
final RenderParagraph trailing = _getTextRenderObject(tester, 'trailing');
|
final RenderParagraph trailing = _getTextRenderObject(tester, 'trailing');
|
||||||
expect(trailing.text.style!.color, theme.textTheme.labelSmall!.color);
|
expect(trailing.text.style!.color, theme.colorScheme.onSurfaceVariant);
|
||||||
});
|
});
|
||||||
|
|
||||||
testWidgets('Default ListTile debugFillProperties', (WidgetTester tester) async {
|
testWidgets('Default ListTile debugFillProperties', (WidgetTester tester) async {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user