-
Notifications
You must be signed in to change notification settings - Fork 27.2k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Update ExpansionTile
to support Material 3 & add an example
#119712
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
// 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. | ||
|
||
import 'template.dart'; | ||
|
||
class ExpansionTileTemplate extends TokenTemplate { | ||
const ExpansionTileTemplate(super.blockName, super.fileName, super.tokens, { | ||
super.colorSchemePrefix = '_colors.', | ||
}); | ||
|
||
@override | ||
String generate() => ''' | ||
class _${blockName}DefaultsM3 extends ExpansionTileThemeData { | ||
_${blockName}DefaultsM3(this.context); | ||
|
||
final BuildContext context; | ||
late final ThemeData _theme = Theme.of(context); | ||
late final ColorScheme _colors = _theme.colorScheme; | ||
|
||
@override | ||
Color? get textColor => ${textStyle("md.comp.list.list-item.label-text")}!.color; | ||
|
||
@override | ||
Color? get iconColor => ${componentColor('md.comp.list.list-item.selected.trailing-icon')}; | ||
|
||
@override | ||
Color? get collapsedTextColor => ${textStyle("md.comp.list.list-item.label-text")}!.color; | ||
|
||
@override | ||
Color? get collapsedIconColor => ${componentColor('md.comp.list.list-item.unselected.trailing-icon')}; | ||
} | ||
'''; | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,40 @@ | ||
// 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. | ||
|
||
import 'package:flutter/material.dart'; | ||
import 'package:flutter_api_samples/material/expansion_tile/expansion_tile.0.dart' as example; | ||
import 'package:flutter_test/flutter_test.dart'; | ||
|
||
void main() { | ||
testWidgets('When expansion tiles are expanded tile numbers are revealed', (WidgetTester tester) async { | ||
const int totalTiles = 3; | ||
|
||
await tester.pumpWidget( | ||
const example.ExpansionTileApp(), | ||
); | ||
|
||
expect(find.byType(ExpansionTile), findsNWidgets(totalTiles)); | ||
|
||
const String tileOne = 'This is tile number 1'; | ||
expect(find.text(tileOne), findsNothing); | ||
|
||
await tester.tap(find.text('ExpansionTile 1')); | ||
await tester.pumpAndSettle(); | ||
expect(find.text(tileOne), findsOneWidget); | ||
|
||
const String tileTwo = 'This is tile number 2'; | ||
expect(find.text(tileTwo), findsNothing); | ||
|
||
await tester.tap(find.text('ExpansionTile 2')); | ||
await tester.pumpAndSettle(); | ||
expect(find.text(tileTwo), findsOneWidget); | ||
|
||
const String tileThree = 'This is tile number 3'; | ||
expect(find.text(tileThree), findsNothing); | ||
|
||
await tester.tap(find.text('ExpansionTile 3')); | ||
await tester.pumpAndSettle(); | ||
expect(find.text(tileThree), findsOneWidget); | ||
}); | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -34,7 +34,8 @@ const Duration _kExpand = Duration(milliseconds: 200); | |
/// to the [leading] and [trailing] properties of [ExpansionTile]. | ||
/// | ||
/// {@tool dartpad} | ||
/// This example demonstrates different configurations of ExpansionTile. | ||
/// This example demonstrates how the [ExpansionTile] icon's location and appearance | ||
/// can be customized. | ||
/// | ||
/// ** See code in examples/api/lib/material/expansion_tile/expansion_tile.0.dart ** | ||
/// {@end-tool} | ||
|
@@ -216,7 +217,7 @@ class ExpansionTile extends StatefulWidget { | |
/// Used to override to the [ListTileThemeData.iconColor]. | ||
/// | ||
/// If this property is null then [ExpansionTileThemeData.iconColor] is used. If that | ||
/// is also null then the value of [ListTileThemeData.iconColor] is used. | ||
/// is also null then the value of [ColorScheme.primary] is used. | ||
/// | ||
/// See also: | ||
/// | ||
|
@@ -227,6 +228,15 @@ class ExpansionTile extends StatefulWidget { | |
/// The icon color of tile's expansion arrow icon when the sublist is collapsed. | ||
/// | ||
/// Used to override to the [ListTileThemeData.iconColor]. | ||
/// | ||
/// If this property is null then [ExpansionTileThemeData.collapsedIconColor] is used. If that | ||
/// is also null and [ThemeData.useMaterial3] is true, [ColorScheme.onSurface] is used. Otherwise, | ||
/// defaults to [ThemeData.unselectedWidgetColor] color. | ||
/// | ||
/// See also: | ||
/// | ||
/// * [ExpansionTileTheme.of], which returns the nearest [ExpansionTileTheme]'s | ||
/// [ExpansionTileThemeData]. | ||
final Color? collapsedIconColor; | ||
|
||
|
||
|
@@ -235,7 +245,8 @@ class ExpansionTile extends StatefulWidget { | |
/// Used to override to the [ListTileThemeData.textColor]. | ||
/// | ||
/// If this property is null then [ExpansionTileThemeData.textColor] is used. If that | ||
/// is also null then the value of [ListTileThemeData.textColor] is used. | ||
/// is also null then and [ThemeData.useMaterial3] is true, color of the [TextTheme.bodyLarge] | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Generally speaking, we do not rely on the TextStyle.color of text theme colors. Presumably there's a token that covers what the text color should be (here and elsewhere). There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Since there is no official expansion tile component. cc: @guidezpl There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Regarding tokens, this is out of spec so there won't be any new ones. |
||
/// will be used for the [title] and [subtitle]. Otherwise, defaults to [ColorScheme.primary] color. | ||
/// | ||
/// See also: | ||
/// | ||
|
@@ -247,8 +258,10 @@ class ExpansionTile extends StatefulWidget { | |
/// | ||
/// Used to override to the [ListTileThemeData.textColor]. | ||
/// | ||
/// If this property is null then [ExpansionTileThemeData.collapsedTextColor] is used. If that | ||
/// is also null then the value of [ListTileThemeData.textColor] is used. | ||
/// If this property is null then [ExpansionTileThemeData.collapsedTextColor] is used. | ||
/// If that is also null and [ThemeData.useMaterial3] is true, color of the | ||
/// [TextTheme.bodyLarge] will be used for the [title] and [subtitle]. Otherwise, | ||
/// defaults to color of the [TextTheme.titleMedium]. | ||
/// | ||
/// See also: | ||
/// | ||
|
@@ -441,7 +454,9 @@ class _ExpansionTileState extends State<ExpansionTile> with SingleTickerProvider | |
void didChangeDependencies() { | ||
final ThemeData theme = Theme.of(context); | ||
final ExpansionTileThemeData expansionTileTheme = ExpansionTileTheme.of(context); | ||
final ColorScheme colorScheme = theme.colorScheme; | ||
final ExpansionTileThemeData defaults = theme.useMaterial3 | ||
? _ExpansionTileDefaultsM3(context) | ||
: _ExpansionTileDefaultsM2(context); | ||
_borderTween | ||
..begin = widget.collapsedShape | ||
?? expansionTileTheme.collapsedShape | ||
|
@@ -458,13 +473,13 @@ class _ExpansionTileState extends State<ExpansionTile> with SingleTickerProvider | |
_headerColorTween | ||
..begin = widget.collapsedTextColor | ||
?? expansionTileTheme.collapsedTextColor | ||
?? theme.textTheme.titleMedium!.color | ||
..end = widget.textColor ?? expansionTileTheme.textColor ?? colorScheme.primary; | ||
?? defaults.collapsedTextColor | ||
..end = widget.textColor ?? expansionTileTheme.textColor ?? defaults.textColor; | ||
_iconColorTween | ||
..begin = widget.collapsedIconColor | ||
?? expansionTileTheme.collapsedIconColor | ||
?? theme.unselectedWidgetColor | ||
..end = widget.iconColor ?? expansionTileTheme.iconColor ?? colorScheme.primary; | ||
?? defaults.collapsedIconColor | ||
..end = widget.iconColor ?? expansionTileTheme.iconColor ?? defaults.iconColor; | ||
_backgroundColorTween | ||
..begin = widget.collapsedBackgroundColor ?? expansionTileTheme.collapsedBackgroundColor | ||
..end = widget.backgroundColor ?? expansionTileTheme.backgroundColor; | ||
|
@@ -498,3 +513,54 @@ class _ExpansionTileState extends State<ExpansionTile> with SingleTickerProvider | |
); | ||
} | ||
} | ||
|
||
class _ExpansionTileDefaultsM2 extends ExpansionTileThemeData { | ||
_ExpansionTileDefaultsM2(this.context); | ||
|
||
final BuildContext context; | ||
late final ThemeData _theme = Theme.of(context); | ||
late final ColorScheme _colorScheme = _theme.colorScheme; | ||
|
||
@override | ||
Color? get textColor => _colorScheme.primary; | ||
|
||
@override | ||
Color? get iconColor => _colorScheme.primary; | ||
|
||
@override | ||
Color? get collapsedTextColor => _theme.textTheme.titleMedium!.color; | ||
|
||
@override | ||
Color? get collapsedIconColor => _theme.unselectedWidgetColor; | ||
} | ||
|
||
// BEGIN GENERATED TOKEN PROPERTIES - ExpansionTile | ||
|
||
// Do not edit by hand. The code between the "BEGIN GENERATED" and | ||
// "END GENERATED" comments are generated from data in the Material | ||
// Design token database by the script: | ||
// dev/tools/gen_defaults/bin/gen_defaults.dart. | ||
|
||
// Token database version: v0_152 | ||
|
||
class _ExpansionTileDefaultsM3 extends ExpansionTileThemeData { | ||
_ExpansionTileDefaultsM3(this.context); | ||
|
||
final BuildContext context; | ||
late final ThemeData _theme = Theme.of(context); | ||
late final ColorScheme _colors = _theme.colorScheme; | ||
|
||
@override | ||
Color? get textColor => Theme.of(context).textTheme.bodyLarge!.color; | ||
|
||
@override | ||
Color? get iconColor => _colors.primary; | ||
|
||
@override | ||
Color? get collapsedTextColor => Theme.of(context).textTheme.bodyLarge!.color; | ||
|
||
@override | ||
Color? get collapsedIconColor => _colors.onSurface; | ||
} | ||
|
||
// END GENERATED TOKEN PROPERTIES - ExpansionTile |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please specify
theme: ThemeData(useMaterial3: true),
We shouldn't be demonstrating M2 anymore.