Unverified Commit cd9a257d authored by Burak İmdat's avatar Burak İmdat Committed by GitHub

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

<details>
  <summary>Title Text Style</summary>
  
  ###  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;
  ```
</details>

<details>
  <summary>Subtitle Text Style</summary>
  
  ## 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`
</details>

<details>
  <summary>Problem solved code</summary>
  
  ## 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!,
      );
  ```
</details>

<details>
<summary>Screenshot of the result after making the necessary change</summary>
<img src="https://github.com/flutter/flutter/assets/70351342/b552fd4c-fdcd-4bf5-b4ba-d6b2cfe527cc" width=250>
</details>

#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].*
parent b0e5a5ca
...@@ -801,8 +801,7 @@ class ListTile extends StatelessWidget { ...@@ -801,8 +801,7 @@ class ListTile extends StatelessWidget {
subtitleStyle = subtitleTextStyle subtitleStyle = subtitleTextStyle
?? tileTheme.subtitleTextStyle ?? tileTheme.subtitleTextStyle
?? defaults.subtitleTextStyle!; ?? defaults.subtitleTextStyle!;
final Color? subtitleColor = effectiveColor 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,
...@@ -1533,7 +1532,8 @@ class _LisTileDefaultsM2 extends ListTileThemeData { ...@@ -1533,7 +1532,8 @@ class _LisTileDefaultsM2 extends ListTileThemeData {
} }
@override @override
TextStyle? get subtitleTextStyle => _textTheme.bodyMedium; TextStyle? get subtitleTextStyle => _textTheme.bodyMedium!
.copyWith(color: _textTheme.bodySmall!.color);
@override @override
TextStyle? get leadingAndTrailingTextStyle => _textTheme.bodyMedium; TextStyle? get leadingAndTrailingTextStyle => _textTheme.bodyMedium;
......
...@@ -393,14 +393,30 @@ void main() { ...@@ -393,14 +393,30 @@ void main() {
}); });
testWidgetsWithLeakTracking( testWidgetsWithLeakTracking(
"ListTile respects ListTileTheme's titleTextStyle, subtitleTextStyle & leadingAndTrailingTextStyle", "Material3 - ListTile respects ListTileTheme's titleTextStyle, subtitleTextStyle & leadingAndTrailingTextStyle",
(WidgetTester tester) async { (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( final ThemeData theme = ThemeData(
useMaterial3: true, useMaterial3: true,
listTileTheme: const ListTileThemeData( listTileTheme: const ListTileThemeData(
titleTextStyle: TextStyle(fontSize: 20.0), titleTextStyle: titleTextStyle,
subtitleTextStyle: TextStyle(fontSize: 17.5), subtitleTextStyle: subtitleTextStyle,
leadingAndTrailingTextStyle: TextStyle(fontSize: 15.0), leadingAndTrailingTextStyle: leadingAndTrailingTextStyle,
), ),
); );
...@@ -426,31 +442,51 @@ void main() { ...@@ -426,31 +442,51 @@ void main() {
await tester.pumpWidget(buildFrame()); await tester.pumpWidget(buildFrame());
final RenderParagraph leading = _getTextRenderObject(tester, 'leading'); 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'); 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'); 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'); 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( testWidgetsWithLeakTracking(
"ListTile's titleTextStyle, subtitleTextStyle & leadingAndTrailingTextStyle are overridden by ListTile properties", "Material2 - ListTile respects ListTileTheme's titleTextStyle, subtitleTextStyle & leadingAndTrailingTextStyle",
(WidgetTester tester) async { (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( final ThemeData theme = ThemeData(
useMaterial3: true, useMaterial3: false,
listTileTheme: const ListTileThemeData( listTileTheme: const ListTileThemeData(
titleTextStyle: TextStyle(fontSize: 20.0), titleTextStyle: titleTextStyle,
subtitleTextStyle: TextStyle(fontSize: 17.5), subtitleTextStyle: subtitleTextStyle,
leadingAndTrailingTextStyle: TextStyle(fontSize: 15.0), 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() { Widget buildFrame() {
return MaterialApp( return MaterialApp(
theme: theme, theme: theme,
...@@ -459,9 +495,6 @@ void main() { ...@@ -459,9 +495,6 @@ void main() {
child: Builder( child: Builder(
builder: (BuildContext context) { builder: (BuildContext context) {
return const ListTile( return const ListTile(
titleTextStyle: titleTextStyle,
subtitleTextStyle: subtitleTextStyle,
leadingAndTrailingTextStyle: leadingAndTrailingTextStyle,
leading: TestText('leading'), leading: TestText('leading'),
title: TestText('title'), title: TestText('title'),
subtitle: TestText('subtitle'), subtitle: TestText('subtitle'),
...@@ -476,13 +509,159 @@ void main() { ...@@ -476,13 +509,159 @@ void main() {
await tester.pumpWidget(buildFrame()); await tester.pumpWidget(buildFrame());
final RenderParagraph leading = _getTextRenderObject(tester, 'leading'); 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'); 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'); 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'); 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 { testWidgetsWithLeakTracking("ListTile respects ListTileTheme's tileColor & selectedTileColor", (WidgetTester tester) async {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment