From cd9a257d741f4593190f56f594cb3441f076aa9d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Burak=20=C4=B0mdat?= <70351342+burakJs@users.noreply.github.com> Date: Wed, 6 Sep 2023 21:54:45 +0300 Subject: [PATCH] Fix `subtitleTextStyle.color` isn't applied to the `ListTile.subtitle` in Material 2 (#133422) The difference between header text style and subtitle text style and the reason why it doesn't work is the code difference below. If we make the subtitle text style the same as the title text style it will work
Title Text Style ### All Code ```dart TextStyle titleStyle = titleTextStyle ?? tileTheme.titleTextStyle ?? defaults.titleTextStyle!; final Color? titleColor = effectiveColor; titleStyle = titleStyle.copyWith( color: titleColor, fontSize: _isDenseLayout(theme, tileTheme) ? 13.0 : null, ); final Widget titleText = AnimatedDefaultTextStyle( style: titleStyle, duration: kThemeChangeDuration, child: title ?? const SizedBox(), ); ``` ## Different Code Section ```dart final Color? titleColor = effectiveColor; ```
Subtitle Text Style ## All Code ```dart subtitleStyle = subtitleTextStyle ?? tileTheme.subtitleTextStyle ?? defaults.subtitleTextStyle!; final Color? subtitleColor = effectiveColor ?? (theme.useMaterial3 ? null : theme.textTheme.bodySmall!.color); subtitleStyle = subtitleStyle.copyWith( color: subtitleColor, fontSize: _isDenseLayout(theme, tileTheme) ? 12.0 : null, ); subtitleText = AnimatedDefaultTextStyle( style: subtitleStyle, duration: kThemeChangeDuration, child: subtitle!, ); ``` ## Different Code Section ```dart final Color? subtitleColor = effectiveColor ?? (theme.useMaterial3 ? null : theme.textTheme.bodySmall!.color); ``` ### Description for code - The value `theme.textTheme.bodySmall!.color` is given because the `effectiveColor` value is `null` and the `theme.useMaterial3` value is `false`
Problem solved code ## All Code ```dart subtitleStyle = subtitleTextStyle ?? tileTheme.subtitleTextStyle ?? defaults.subtitleTextStyle!; final Color? subtitleColor = effectiveColor; subtitleStyle = subtitleStyle.copyWith( color: subtitleColor, fontSize: _isDenseLayout(theme, tileTheme) ? 12.0 : null, ); subtitleText = AnimatedDefaultTextStyle( style: subtitleStyle, duration: kThemeChangeDuration, child: subtitle!, ); ```
Screenshot of the result after making the necessary change
#133412 *If you had to change anything in the [flutter/tests] repo, include a link to the migration guide as per the [breaking change policy].* --- .../flutter/lib/src/material/list_tile.dart | 6 +- .../test/material/list_tile_theme_test.dart | 229 ++++++++++++++++-- 2 files changed, 207 insertions(+), 28 deletions(-) diff --git a/packages/flutter/lib/src/material/list_tile.dart b/packages/flutter/lib/src/material/list_tile.dart index 074862beb3..741787207d 100644 --- a/packages/flutter/lib/src/material/list_tile.dart +++ b/packages/flutter/lib/src/material/list_tile.dart @@ -801,8 +801,7 @@ class ListTile extends StatelessWidget { subtitleStyle = subtitleTextStyle ?? tileTheme.subtitleTextStyle ?? defaults.subtitleTextStyle!; - final Color? subtitleColor = effectiveColor - ?? (theme.useMaterial3 ? null : theme.textTheme.bodySmall!.color); + final Color? subtitleColor = effectiveColor; subtitleStyle = subtitleStyle.copyWith( color: subtitleColor, fontSize: _isDenseLayout(theme, tileTheme) ? 12.0 : null, @@ -1533,7 +1532,8 @@ class _LisTileDefaultsM2 extends ListTileThemeData { } @override - TextStyle? get subtitleTextStyle => _textTheme.bodyMedium; + TextStyle? get subtitleTextStyle => _textTheme.bodyMedium! + .copyWith(color: _textTheme.bodySmall!.color); @override TextStyle? get leadingAndTrailingTextStyle => _textTheme.bodyMedium; diff --git a/packages/flutter/test/material/list_tile_theme_test.dart b/packages/flutter/test/material/list_tile_theme_test.dart index 8b92ae3ab6..f779e489b9 100644 --- a/packages/flutter/test/material/list_tile_theme_test.dart +++ b/packages/flutter/test/material/list_tile_theme_test.dart @@ -393,14 +393,30 @@ void main() { }); testWidgetsWithLeakTracking( - "ListTile respects ListTileTheme's titleTextStyle, subtitleTextStyle & leadingAndTrailingTextStyle", + "Material3 - ListTile respects ListTileTheme's titleTextStyle, subtitleTextStyle & leadingAndTrailingTextStyle", (WidgetTester tester) async { + const TextStyle titleTextStyle = TextStyle( + fontSize: 23.0, + color: Color(0xffff0000), + fontStyle: FontStyle.italic, + ); + const TextStyle subtitleTextStyle = TextStyle( + fontSize: 20.0, + color: Color(0xff00ff00), + fontStyle: FontStyle.italic, + ); + const TextStyle leadingAndTrailingTextStyle = TextStyle( + fontSize: 18.0, + color: Color(0xff0000ff), + fontStyle: FontStyle.italic, + ); + final ThemeData theme = ThemeData( useMaterial3: true, listTileTheme: const ListTileThemeData( - titleTextStyle: TextStyle(fontSize: 20.0), - subtitleTextStyle: TextStyle(fontSize: 17.5), - leadingAndTrailingTextStyle: TextStyle(fontSize: 15.0), + titleTextStyle: titleTextStyle, + subtitleTextStyle: subtitleTextStyle, + leadingAndTrailingTextStyle: leadingAndTrailingTextStyle, ), ); @@ -426,31 +442,51 @@ void main() { await tester.pumpWidget(buildFrame()); final RenderParagraph leading = _getTextRenderObject(tester, 'leading'); - expect(leading.text.style!.fontSize, 15.0); + expect(leading.text.style!.fontSize, leadingAndTrailingTextStyle.fontSize); + expect(leading.text.style!.color, leadingAndTrailingTextStyle.color); + expect(leading.text.style!.fontStyle, leadingAndTrailingTextStyle.fontStyle); final RenderParagraph title = _getTextRenderObject(tester, 'title'); - expect(title.text.style!.fontSize, 20.0); + expect(title.text.style!.fontSize, titleTextStyle.fontSize); + expect(title.text.style!.color, titleTextStyle.color); + expect(title.text.style!.fontStyle, titleTextStyle.fontStyle); final RenderParagraph subtitle = _getTextRenderObject(tester, 'subtitle'); - expect(subtitle.text.style!.fontSize, 17.5); + expect(subtitle.text.style!.fontSize, subtitleTextStyle.fontSize); + expect(subtitle.text.style!.color, subtitleTextStyle.color); + expect(subtitle.text.style!.fontStyle, subtitleTextStyle.fontStyle); final RenderParagraph trailing = _getTextRenderObject(tester, 'trailing'); - expect(trailing.text.style!.fontSize, 15.0); + expect(trailing.text.style!.fontSize, leadingAndTrailingTextStyle.fontSize); + expect(trailing.text.style!.color, leadingAndTrailingTextStyle.color); + expect(trailing.text.style!.fontStyle, leadingAndTrailingTextStyle.fontStyle); }); testWidgetsWithLeakTracking( - "ListTile's titleTextStyle, subtitleTextStyle & leadingAndTrailingTextStyle are overridden by ListTile properties", + "Material2 - ListTile respects ListTileTheme's titleTextStyle, subtitleTextStyle & leadingAndTrailingTextStyle", (WidgetTester tester) async { + const TextStyle titleTextStyle = TextStyle( + fontSize: 23.0, + color: Color(0xffff0000), + fontStyle: FontStyle.italic, + ); + const TextStyle subtitleTextStyle = TextStyle( + fontSize: 20.0, + color: Color(0xff00ff00), + fontStyle: FontStyle.italic, + ); + const TextStyle leadingAndTrailingTextStyle = TextStyle( + fontSize: 18.0, + color: Color(0xff0000ff), + fontStyle: FontStyle.italic, + ); + final ThemeData theme = ThemeData( - useMaterial3: true, - listTileTheme: const ListTileThemeData( - titleTextStyle: TextStyle(fontSize: 20.0), - subtitleTextStyle: TextStyle(fontSize: 17.5), - leadingAndTrailingTextStyle: TextStyle(fontSize: 15.0), + useMaterial3: false, + listTileTheme: const ListTileThemeData( + titleTextStyle: titleTextStyle, + subtitleTextStyle: subtitleTextStyle, + leadingAndTrailingTextStyle: leadingAndTrailingTextStyle, ), ); - const TextStyle titleTextStyle = TextStyle(fontSize: 23.0); - const TextStyle subtitleTextStyle = TextStyle(fontSize: 20.0); - const TextStyle leadingAndTrailingTextStyle = TextStyle(fontSize: 18.0); - Widget buildFrame() { return MaterialApp( theme: theme, @@ -459,9 +495,6 @@ void main() { child: Builder( builder: (BuildContext context) { return const ListTile( - titleTextStyle: titleTextStyle, - subtitleTextStyle: subtitleTextStyle, - leadingAndTrailingTextStyle: leadingAndTrailingTextStyle, leading: TestText('leading'), title: TestText('title'), subtitle: TestText('subtitle'), @@ -476,13 +509,159 @@ void main() { await tester.pumpWidget(buildFrame()); final RenderParagraph leading = _getTextRenderObject(tester, 'leading'); - expect(leading.text.style!.fontSize, 18.0); + expect(leading.text.style!.fontSize, leadingAndTrailingTextStyle.fontSize); + expect(leading.text.style!.color, leadingAndTrailingTextStyle.color); + expect(leading.text.style!.fontStyle, leadingAndTrailingTextStyle.fontStyle); final RenderParagraph title = _getTextRenderObject(tester, 'title'); - expect(title.text.style!.fontSize, 23.0); + expect(title.text.style!.fontSize, titleTextStyle.fontSize); + expect(title.text.style!.color, titleTextStyle.color); + expect(title.text.style!.fontStyle, titleTextStyle.fontStyle); final RenderParagraph subtitle = _getTextRenderObject(tester, 'subtitle'); - expect(subtitle.text.style!.fontSize, 20.0); + expect(subtitle.text.style!.fontSize, subtitleTextStyle.fontSize); + expect(subtitle.text.style!.color, subtitleTextStyle.color); + expect(subtitle.text.style!.fontStyle, subtitleTextStyle.fontStyle); final RenderParagraph trailing = _getTextRenderObject(tester, 'trailing'); - expect(trailing.text.style!.fontSize, 18.0); + expect(trailing.text.style!.fontSize, leadingAndTrailingTextStyle.fontSize); + expect(trailing.text.style!.color, leadingAndTrailingTextStyle.color); + expect(trailing.text.style!.fontStyle, leadingAndTrailingTextStyle.fontStyle); + }); + + testWidgetsWithLeakTracking( + "Material3 - ListTile's titleTextStyle, subtitleTextStyle & leadingAndTrailingTextStyle are overridden by ListTile properties", + (WidgetTester tester) async { + final ThemeData theme = ThemeData( + useMaterial3: true, + listTileTheme: const ListTileThemeData( + titleTextStyle: TextStyle(fontSize: 20.0), + subtitleTextStyle: TextStyle(fontSize: 17.5), + leadingAndTrailingTextStyle: TextStyle(fontSize: 15.0), + ), + ); + const TextStyle titleTextStyle = TextStyle( + fontSize: 23.0, + color: Color(0xffff0000), + fontStyle: FontStyle.italic, + ); + const TextStyle subtitleTextStyle = TextStyle( + fontSize: 20.0, + color: Color(0xff00ff00), + fontStyle: FontStyle.italic, + ); + const TextStyle leadingAndTrailingTextStyle = TextStyle( + fontSize: 18.0, + color: Color(0xff0000ff), + fontStyle: FontStyle.italic, + ); + + Widget buildFrame() { + return MaterialApp( + theme: theme, + home: Material( + child: Center( + child: Builder( + builder: (BuildContext context) { + return const ListTile( + titleTextStyle: titleTextStyle, + subtitleTextStyle: subtitleTextStyle, + leadingAndTrailingTextStyle: leadingAndTrailingTextStyle, + leading: TestText('leading'), + title: TestText('title'), + subtitle: TestText('subtitle'), + trailing: TestText('trailing'), + ); + }, + ), + ), + ), + ); + } + + await tester.pumpWidget(buildFrame()); + final RenderParagraph leading = _getTextRenderObject(tester, 'leading'); + expect(leading.text.style!.fontSize, leadingAndTrailingTextStyle.fontSize); + expect(leading.text.style!.color, leadingAndTrailingTextStyle.color); + expect(leading.text.style!.fontStyle, leadingAndTrailingTextStyle.fontStyle); + final RenderParagraph title = _getTextRenderObject(tester, 'title'); + expect(title.text.style!.fontSize, titleTextStyle.fontSize); + expect(title.text.style!.color, titleTextStyle.color); + expect(title.text.style!.fontStyle, titleTextStyle.fontStyle); + final RenderParagraph subtitle = _getTextRenderObject(tester, 'subtitle'); + expect(subtitle.text.style!.fontSize, subtitleTextStyle.fontSize); + expect(subtitle.text.style!.color, subtitleTextStyle.color); + expect(subtitle.text.style!.fontStyle, subtitleTextStyle.fontStyle); + final RenderParagraph trailing = _getTextRenderObject(tester, 'trailing'); + expect(trailing.text.style!.fontSize, leadingAndTrailingTextStyle.fontSize); + expect(trailing.text.style!.color, leadingAndTrailingTextStyle.color); + expect(trailing.text.style!.fontStyle, leadingAndTrailingTextStyle.fontStyle); + }); + + testWidgetsWithLeakTracking( + "Material2 - ListTile's titleTextStyle, subtitleTextStyle & leadingAndTrailingTextStyle are overridden by ListTile properties", + (WidgetTester tester) async { + final ThemeData theme = ThemeData( + useMaterial3: false, + listTileTheme: const ListTileThemeData( + titleTextStyle: TextStyle(fontSize: 20.0), + subtitleTextStyle: TextStyle(fontSize: 17.5), + leadingAndTrailingTextStyle: TextStyle(fontSize: 15.0), + ), + ); + const TextStyle titleTextStyle = TextStyle( + fontSize: 23.0, + color: Color(0xffff0000), + fontStyle: FontStyle.italic, + ); + const TextStyle subtitleTextStyle = TextStyle( + fontSize: 20.0, + color: Color(0xff00ff00), + fontStyle: FontStyle.italic, + ); + const TextStyle leadingAndTrailingTextStyle = TextStyle( + fontSize: 18.0, + color: Color(0xff0000ff), + fontStyle: FontStyle.italic, + ); + + Widget buildFrame() { + return MaterialApp( + theme: theme, + home: Material( + child: Center( + child: Builder( + builder: (BuildContext context) { + return const ListTile( + titleTextStyle: titleTextStyle, + subtitleTextStyle: subtitleTextStyle, + leadingAndTrailingTextStyle: leadingAndTrailingTextStyle, + leading: TestText('leading'), + title: TestText('title'), + subtitle: TestText('subtitle'), + trailing: TestText('trailing'), + ); + }, + ), + ), + ), + ); + } + + await tester.pumpWidget(buildFrame()); + final RenderParagraph leading = _getTextRenderObject(tester, 'leading'); + expect(leading.text.style!.fontSize, leadingAndTrailingTextStyle.fontSize); + expect(leading.text.style!.color, leadingAndTrailingTextStyle.color); + expect(leading.text.style!.fontStyle, leadingAndTrailingTextStyle.fontStyle); + final RenderParagraph title = _getTextRenderObject(tester, 'title'); + expect(title.text.style!.fontSize, titleTextStyle.fontSize); + expect(title.text.style!.color, titleTextStyle.color); + expect(title.text.style!.fontStyle, titleTextStyle.fontStyle); + final RenderParagraph subtitle = _getTextRenderObject(tester, 'subtitle'); + expect(subtitle.text.style!.fontSize, subtitleTextStyle.fontSize); + expect(subtitle.text.style!.color, subtitleTextStyle.color); + expect(subtitle.text.style!.fontStyle, subtitleTextStyle.fontStyle); + final RenderParagraph trailing = _getTextRenderObject(tester, 'trailing'); + expect(trailing.text.style!.fontSize, leadingAndTrailingTextStyle.fontSize); + expect(trailing.text.style!.color, leadingAndTrailingTextStyle.color); + expect(trailing.text.style!.fontStyle, leadingAndTrailingTextStyle.fontStyle); }); testWidgetsWithLeakTracking("ListTile respects ListTileTheme's tileColor & selectedTileColor", (WidgetTester tester) async {