mirror of
https://github.com/flutter/flutter.git
synced 2025-06-03 00:51:18 +00:00
fix(ListTileTheme): isThreeLine is missing. (#165481)
fix: https://github.com/flutter/flutter/issues/165453 ## Pre-launch Checklist - [x] I read the [Contributor Guide] and followed the process outlined there for submitting PRs. - [x] I read the [Tree Hygiene] wiki page, which explains my responsibilities. - [x] I read and followed the [Flutter Style Guide], including [Features we expect every widget to implement]. - [x] I signed the [CLA]. - [x] I listed at least one issue that this PR fixes in the description above. - [x] I updated/added relevant documentation (doc comments with `///`). - [x] I added new tests to check the change I am making, or this PR is [test-exempt]. - [x] I followed the [breaking change policy] and added [Data Driven Fixes] where supported. - [x] All existing and new tests are passing.
This commit is contained in:
parent
7ab8ce9638
commit
9c4e49ea78
@ -393,7 +393,7 @@ class ListTile extends StatelessWidget {
|
|||||||
this.title,
|
this.title,
|
||||||
this.subtitle,
|
this.subtitle,
|
||||||
this.trailing,
|
this.trailing,
|
||||||
this.isThreeLine = false,
|
this.isThreeLine,
|
||||||
this.dense,
|
this.dense,
|
||||||
this.visualDensity,
|
this.visualDensity,
|
||||||
this.shape,
|
this.shape,
|
||||||
@ -425,7 +425,7 @@ class ListTile extends StatelessWidget {
|
|||||||
this.minTileHeight,
|
this.minTileHeight,
|
||||||
this.titleAlignment,
|
this.titleAlignment,
|
||||||
this.internalAddSemanticForOnTap = true,
|
this.internalAddSemanticForOnTap = true,
|
||||||
}) : assert(!isThreeLine || subtitle != null);
|
}) : assert(isThreeLine != true || subtitle != null);
|
||||||
|
|
||||||
/// A widget to display before the title.
|
/// A widget to display before the title.
|
||||||
///
|
///
|
||||||
@ -482,7 +482,12 @@ class ListTile extends StatelessWidget {
|
|||||||
///
|
///
|
||||||
/// When using a [Text] widget for [title] and [subtitle], you can enforce
|
/// When using a [Text] widget for [title] and [subtitle], you can enforce
|
||||||
/// line limits using [Text.maxLines].
|
/// line limits using [Text.maxLines].
|
||||||
final bool isThreeLine;
|
///
|
||||||
|
/// See also:
|
||||||
|
///
|
||||||
|
/// * [ListTileTheme.of], which returns the nearest [ListTileTheme]'s
|
||||||
|
/// [ListTileThemeData].
|
||||||
|
final bool? isThreeLine;
|
||||||
|
|
||||||
/// {@template flutter.material.ListTile.dense}
|
/// {@template flutter.material.ListTile.dense}
|
||||||
/// Whether this list tile is part of a vertically dense list.
|
/// Whether this list tile is part of a vertically dense list.
|
||||||
@ -987,7 +992,11 @@ class ListTile extends StatelessWidget {
|
|||||||
trailing: trailingIcon,
|
trailing: trailingIcon,
|
||||||
isDense: _isDenseLayout(theme, tileTheme),
|
isDense: _isDenseLayout(theme, tileTheme),
|
||||||
visualDensity: visualDensity ?? tileTheme.visualDensity ?? theme.visualDensity,
|
visualDensity: visualDensity ?? tileTheme.visualDensity ?? theme.visualDensity,
|
||||||
isThreeLine: isThreeLine,
|
isThreeLine:
|
||||||
|
isThreeLine ??
|
||||||
|
tileTheme.isThreeLine ??
|
||||||
|
theme.listTileTheme.isThreeLine ??
|
||||||
|
false,
|
||||||
textDirection: textDirection,
|
textDirection: textDirection,
|
||||||
titleBaselineType:
|
titleBaselineType:
|
||||||
titleStyle.textBaseline ?? defaults.titleTextStyle!.textBaseline!,
|
titleStyle.textBaseline ?? defaults.titleTextStyle!.textBaseline!,
|
||||||
@ -1021,7 +1030,6 @@ class ListTile extends StatelessWidget {
|
|||||||
ifTrue: 'THREE_LINE',
|
ifTrue: 'THREE_LINE',
|
||||||
ifFalse: 'TWO_LINE',
|
ifFalse: 'TWO_LINE',
|
||||||
showName: true,
|
showName: true,
|
||||||
defaultValue: false,
|
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
properties.add(
|
properties.add(
|
||||||
|
@ -73,6 +73,7 @@ class ListTileThemeData with Diagnosticable {
|
|||||||
this.minTileHeight,
|
this.minTileHeight,
|
||||||
this.titleAlignment,
|
this.titleAlignment,
|
||||||
this.controlAffinity,
|
this.controlAffinity,
|
||||||
|
this.isThreeLine,
|
||||||
});
|
});
|
||||||
|
|
||||||
/// Overrides the default value of [ListTile.dense].
|
/// Overrides the default value of [ListTile.dense].
|
||||||
@ -139,6 +140,9 @@ class ListTileThemeData with Diagnosticable {
|
|||||||
/// or [ExpansionTile.controlAffinity] or [SwitchListTile.controlAffinity] or [RadioListTile.controlAffinity].
|
/// or [ExpansionTile.controlAffinity] or [SwitchListTile.controlAffinity] or [RadioListTile.controlAffinity].
|
||||||
final ListTileControlAffinity? controlAffinity;
|
final ListTileControlAffinity? controlAffinity;
|
||||||
|
|
||||||
|
/// If specified, overrides the default value of [ListTile.isThreeLine].
|
||||||
|
final bool? isThreeLine;
|
||||||
|
|
||||||
/// Creates a copy of this object with the given fields replaced with the
|
/// Creates a copy of this object with the given fields replaced with the
|
||||||
/// new values.
|
/// new values.
|
||||||
ListTileThemeData copyWith({
|
ListTileThemeData copyWith({
|
||||||
@ -187,6 +191,7 @@ class ListTileThemeData with Diagnosticable {
|
|||||||
visualDensity: visualDensity ?? this.visualDensity,
|
visualDensity: visualDensity ?? this.visualDensity,
|
||||||
titleAlignment: titleAlignment ?? this.titleAlignment,
|
titleAlignment: titleAlignment ?? this.titleAlignment,
|
||||||
controlAffinity: controlAffinity ?? this.controlAffinity,
|
controlAffinity: controlAffinity ?? this.controlAffinity,
|
||||||
|
isThreeLine: isThreeLine ?? this.isThreeLine,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -221,6 +226,7 @@ class ListTileThemeData with Diagnosticable {
|
|||||||
visualDensity: t < 0.5 ? a?.visualDensity : b?.visualDensity,
|
visualDensity: t < 0.5 ? a?.visualDensity : b?.visualDensity,
|
||||||
titleAlignment: t < 0.5 ? a?.titleAlignment : b?.titleAlignment,
|
titleAlignment: t < 0.5 ? a?.titleAlignment : b?.titleAlignment,
|
||||||
controlAffinity: t < 0.5 ? a?.controlAffinity : b?.controlAffinity,
|
controlAffinity: t < 0.5 ? a?.controlAffinity : b?.controlAffinity,
|
||||||
|
isThreeLine: t < 0.5 ? a?.isThreeLine : b?.isThreeLine,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -247,6 +253,7 @@ class ListTileThemeData with Diagnosticable {
|
|||||||
visualDensity,
|
visualDensity,
|
||||||
titleAlignment,
|
titleAlignment,
|
||||||
controlAffinity,
|
controlAffinity,
|
||||||
|
isThreeLine,
|
||||||
]);
|
]);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@ -278,7 +285,8 @@ class ListTileThemeData with Diagnosticable {
|
|||||||
other.mouseCursor == mouseCursor &&
|
other.mouseCursor == mouseCursor &&
|
||||||
other.visualDensity == visualDensity &&
|
other.visualDensity == visualDensity &&
|
||||||
other.titleAlignment == titleAlignment &&
|
other.titleAlignment == titleAlignment &&
|
||||||
other.controlAffinity == controlAffinity;
|
other.controlAffinity == controlAffinity &&
|
||||||
|
other.isThreeLine == isThreeLine;
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@ -337,6 +345,7 @@ class ListTileThemeData with Diagnosticable {
|
|||||||
defaultValue: null,
|
defaultValue: null,
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
properties.add(DiagnosticsProperty<bool>('isThreeLine', isThreeLine, defaultValue: null));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -573,6 +582,7 @@ class ListTileTheme extends InheritedTheme {
|
|||||||
MaterialStateProperty<MouseCursor?>? mouseCursor,
|
MaterialStateProperty<MouseCursor?>? mouseCursor,
|
||||||
VisualDensity? visualDensity,
|
VisualDensity? visualDensity,
|
||||||
ListTileControlAffinity? controlAffinity,
|
ListTileControlAffinity? controlAffinity,
|
||||||
|
bool? isThreeLine,
|
||||||
required Widget child,
|
required Widget child,
|
||||||
}) {
|
}) {
|
||||||
return Builder(
|
return Builder(
|
||||||
@ -603,6 +613,7 @@ class ListTileTheme extends InheritedTheme {
|
|||||||
mouseCursor: mouseCursor ?? parent.mouseCursor,
|
mouseCursor: mouseCursor ?? parent.mouseCursor,
|
||||||
visualDensity: visualDensity ?? parent.visualDensity,
|
visualDensity: visualDensity ?? parent.visualDensity,
|
||||||
controlAffinity: controlAffinity ?? parent.controlAffinity,
|
controlAffinity: controlAffinity ?? parent.controlAffinity,
|
||||||
|
isThreeLine: isThreeLine ?? parent.isThreeLine,
|
||||||
),
|
),
|
||||||
child: child,
|
child: child,
|
||||||
);
|
);
|
||||||
@ -627,6 +638,7 @@ class ListTileTheme extends InheritedTheme {
|
|||||||
horizontalTitleGap: horizontalTitleGap,
|
horizontalTitleGap: horizontalTitleGap,
|
||||||
minVerticalPadding: minVerticalPadding,
|
minVerticalPadding: minVerticalPadding,
|
||||||
minLeadingWidth: minLeadingWidth,
|
minLeadingWidth: minLeadingWidth,
|
||||||
|
isThreeLine: _data?.isThreeLine,
|
||||||
),
|
),
|
||||||
child: child,
|
child: child,
|
||||||
);
|
);
|
||||||
|
@ -4361,6 +4361,138 @@ void main() {
|
|||||||
expect(trailingOffset.dy - tileOffset.dy, minVerticalPadding);
|
expect(trailingOffset.dy - tileOffset.dy, minVerticalPadding);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Regression test for https://github.com/flutter/flutter/issues/165453
|
||||||
|
testWidgets('ListTile isThreeLine', (WidgetTester tester) async {
|
||||||
|
const double height = 300;
|
||||||
|
const double avatarTop = 130.0;
|
||||||
|
const double placeholderTop = 138.0;
|
||||||
|
|
||||||
|
Widget buildFrame({bool? themeDataIsThreeLine, bool? themeIsThreeLine, bool? isThreeLine}) {
|
||||||
|
return MaterialApp(
|
||||||
|
key: UniqueKey(),
|
||||||
|
theme:
|
||||||
|
themeDataIsThreeLine != null
|
||||||
|
? ThemeData(listTileTheme: ListTileThemeData(isThreeLine: themeDataIsThreeLine))
|
||||||
|
: null,
|
||||||
|
home: Material(
|
||||||
|
child: ListTileTheme(
|
||||||
|
data:
|
||||||
|
themeIsThreeLine != null ? ListTileThemeData(isThreeLine: themeIsThreeLine) : null,
|
||||||
|
child: ListView(
|
||||||
|
children: <Widget>[
|
||||||
|
ListTile(
|
||||||
|
isThreeLine: isThreeLine,
|
||||||
|
leading: const CircleAvatar(),
|
||||||
|
trailing: const SizedBox(height: 24.0, width: 24.0, child: Placeholder()),
|
||||||
|
title: const Text('A'),
|
||||||
|
subtitle: const Text('A\nB\nC\nD\nE\nF\nG\nH\nI\nJ\nK\nL\nM'),
|
||||||
|
),
|
||||||
|
ListTile(
|
||||||
|
isThreeLine: isThreeLine,
|
||||||
|
leading: const CircleAvatar(),
|
||||||
|
trailing: const SizedBox(height: 24.0, width: 24.0, child: Placeholder()),
|
||||||
|
title: const Text('A'),
|
||||||
|
subtitle: const Text('A'),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
void expectTwoLine() {
|
||||||
|
expect(
|
||||||
|
tester.getRect(find.byType(ListTile).at(0)),
|
||||||
|
const Rect.fromLTWH(0.0, 0.0, 800.0, height),
|
||||||
|
);
|
||||||
|
expect(
|
||||||
|
tester.getRect(find.byType(CircleAvatar).at(0)),
|
||||||
|
const Rect.fromLTWH(16.0, avatarTop, 40.0, 40.0),
|
||||||
|
);
|
||||||
|
expect(
|
||||||
|
tester.getRect(find.byType(Placeholder).at(0)),
|
||||||
|
const Rect.fromLTWH(800.0 - 24.0 - 24.0, placeholderTop, 24.0, 24.0),
|
||||||
|
);
|
||||||
|
expect(
|
||||||
|
tester.getRect(find.byType(ListTile).at(1)),
|
||||||
|
const Rect.fromLTWH(0.0, height, 800.0, 72.0),
|
||||||
|
);
|
||||||
|
expect(
|
||||||
|
tester.getRect(find.byType(CircleAvatar).at(1)),
|
||||||
|
const Rect.fromLTWH(16.0, height + 16.0, 40.0, 40.0),
|
||||||
|
);
|
||||||
|
expect(
|
||||||
|
tester.getRect(find.byType(Placeholder).at(1)),
|
||||||
|
const Rect.fromLTWH(800.0 - 24.0 - 24.0, height + 24.0, 24.0, 24.0),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
void expectThreeLine() {
|
||||||
|
expect(
|
||||||
|
tester.getRect(find.byType(ListTile).at(0)),
|
||||||
|
const Rect.fromLTWH(0.0, 0.0, 800.0, height),
|
||||||
|
);
|
||||||
|
expect(
|
||||||
|
tester.getRect(find.byType(CircleAvatar).at(0)),
|
||||||
|
const Rect.fromLTWH(16.0, 8.0, 40.0, 40.0),
|
||||||
|
);
|
||||||
|
expect(
|
||||||
|
tester.getRect(find.byType(Placeholder).at(0)),
|
||||||
|
const Rect.fromLTWH(800.0 - 24.0 - 24.0, 8.0, 24.0, 24.0),
|
||||||
|
);
|
||||||
|
expect(
|
||||||
|
tester.getRect(find.byType(ListTile).at(1)),
|
||||||
|
const Rect.fromLTWH(0.0, height, 800.0, 88.0),
|
||||||
|
);
|
||||||
|
expect(
|
||||||
|
tester.getRect(find.byType(CircleAvatar).at(1)),
|
||||||
|
const Rect.fromLTWH(16.0, height + 8.0, 40.0, 40.0),
|
||||||
|
);
|
||||||
|
expect(
|
||||||
|
tester.getRect(find.byType(Placeholder).at(1)),
|
||||||
|
const Rect.fromLTWH(800.0 - 24.0 - 24.0, height + 8.0, 24.0, 24.0),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
await tester.pumpWidget(buildFrame());
|
||||||
|
expectTwoLine();
|
||||||
|
|
||||||
|
await tester.pumpWidget(buildFrame(themeDataIsThreeLine: true));
|
||||||
|
expectThreeLine();
|
||||||
|
|
||||||
|
await tester.pumpWidget(buildFrame(themeDataIsThreeLine: false, themeIsThreeLine: true));
|
||||||
|
expectThreeLine();
|
||||||
|
|
||||||
|
await tester.pumpWidget(buildFrame(themeDataIsThreeLine: true, themeIsThreeLine: false));
|
||||||
|
expectTwoLine();
|
||||||
|
|
||||||
|
await tester.pumpWidget(buildFrame(isThreeLine: true));
|
||||||
|
expectThreeLine();
|
||||||
|
|
||||||
|
await tester.pumpWidget(buildFrame(themeIsThreeLine: true, isThreeLine: false));
|
||||||
|
expectTwoLine();
|
||||||
|
|
||||||
|
await tester.pumpWidget(buildFrame(themeDataIsThreeLine: true, isThreeLine: false));
|
||||||
|
expectTwoLine();
|
||||||
|
|
||||||
|
await tester.pumpWidget(
|
||||||
|
buildFrame(themeDataIsThreeLine: true, themeIsThreeLine: true, isThreeLine: false),
|
||||||
|
);
|
||||||
|
expectTwoLine();
|
||||||
|
|
||||||
|
await tester.pumpWidget(buildFrame(themeIsThreeLine: false, isThreeLine: true));
|
||||||
|
expectThreeLine();
|
||||||
|
|
||||||
|
await tester.pumpWidget(buildFrame(themeDataIsThreeLine: false, isThreeLine: true));
|
||||||
|
expectThreeLine();
|
||||||
|
|
||||||
|
await tester.pumpWidget(
|
||||||
|
buildFrame(themeDataIsThreeLine: false, themeIsThreeLine: false, isThreeLine: true),
|
||||||
|
);
|
||||||
|
expectThreeLine();
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
RenderParagraph _getTextRenderObject(WidgetTester tester, String text) {
|
RenderParagraph _getTextRenderObject(WidgetTester tester, String text) {
|
||||||
|
@ -77,6 +77,7 @@ void main() {
|
|||||||
expect(themeData.mouseCursor, null);
|
expect(themeData.mouseCursor, null);
|
||||||
expect(themeData.visualDensity, null);
|
expect(themeData.visualDensity, null);
|
||||||
expect(themeData.titleAlignment, null);
|
expect(themeData.titleAlignment, null);
|
||||||
|
expect(themeData.isThreeLine, null);
|
||||||
});
|
});
|
||||||
|
|
||||||
testWidgets('Default ListTileThemeData debugFillProperties', (WidgetTester tester) async {
|
testWidgets('Default ListTileThemeData debugFillProperties', (WidgetTester tester) async {
|
||||||
@ -115,6 +116,7 @@ void main() {
|
|||||||
mouseCursor: MaterialStateMouseCursor.clickable,
|
mouseCursor: MaterialStateMouseCursor.clickable,
|
||||||
visualDensity: VisualDensity.comfortable,
|
visualDensity: VisualDensity.comfortable,
|
||||||
titleAlignment: ListTileTitleAlignment.top,
|
titleAlignment: ListTileTitleAlignment.top,
|
||||||
|
isThreeLine: true,
|
||||||
).debugFillProperties(builder);
|
).debugFillProperties(builder);
|
||||||
|
|
||||||
final List<String> description =
|
final List<String> description =
|
||||||
@ -146,6 +148,7 @@ void main() {
|
|||||||
'mouseCursor: WidgetStateMouseCursor(clickable)',
|
'mouseCursor: WidgetStateMouseCursor(clickable)',
|
||||||
'visualDensity: VisualDensity#00000(h: -1.0, v: -1.0)(horizontal: -1.0, vertical: -1.0)',
|
'visualDensity: VisualDensity#00000(h: -1.0, v: -1.0)(horizontal: -1.0, vertical: -1.0)',
|
||||||
'titleAlignment: ListTileTitleAlignment.top',
|
'titleAlignment: ListTileTitleAlignment.top',
|
||||||
|
'isThreeLine: true',
|
||||||
]),
|
]),
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
@ -937,6 +940,7 @@ void main() {
|
|||||||
minTileHeight: 30,
|
minTileHeight: 30,
|
||||||
enableFeedback: true,
|
enableFeedback: true,
|
||||||
titleAlignment: ListTileTitleAlignment.bottom,
|
titleAlignment: ListTileTitleAlignment.bottom,
|
||||||
|
isThreeLine: true,
|
||||||
);
|
);
|
||||||
|
|
||||||
final ListTileThemeData copy = original.copyWith(
|
final ListTileThemeData copy = original.copyWith(
|
||||||
@ -958,6 +962,7 @@ void main() {
|
|||||||
minTileHeight: 80,
|
minTileHeight: 80,
|
||||||
enableFeedback: false,
|
enableFeedback: false,
|
||||||
titleAlignment: ListTileTitleAlignment.top,
|
titleAlignment: ListTileTitleAlignment.top,
|
||||||
|
isThreeLine: false,
|
||||||
);
|
);
|
||||||
|
|
||||||
expect(copy.dense, false);
|
expect(copy.dense, false);
|
||||||
@ -978,6 +983,7 @@ void main() {
|
|||||||
expect(copy.minTileHeight, 80);
|
expect(copy.minTileHeight, 80);
|
||||||
expect(copy.enableFeedback, false);
|
expect(copy.enableFeedback, false);
|
||||||
expect(copy.titleAlignment, ListTileTitleAlignment.top);
|
expect(copy.titleAlignment, ListTileTitleAlignment.top);
|
||||||
|
expect(copy.isThreeLine, false);
|
||||||
});
|
});
|
||||||
|
|
||||||
testWidgets('ListTileTheme.titleAlignment is overridden by ListTile.titleAlignment', (
|
testWidgets('ListTileTheme.titleAlignment is overridden by ListTile.titleAlignment', (
|
||||||
@ -1040,6 +1046,7 @@ void main() {
|
|||||||
titleAlignment: ListTileTitleAlignment.bottom,
|
titleAlignment: ListTileTitleAlignment.bottom,
|
||||||
mouseCursor: MaterialStateMouseCursor.textable,
|
mouseCursor: MaterialStateMouseCursor.textable,
|
||||||
visualDensity: VisualDensity.comfortable,
|
visualDensity: VisualDensity.comfortable,
|
||||||
|
isThreeLine: true,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
home: Material(
|
home: Material(
|
||||||
@ -1067,6 +1074,7 @@ void main() {
|
|||||||
titleAlignment: ListTileTitleAlignment.top,
|
titleAlignment: ListTileTitleAlignment.top,
|
||||||
mouseCursor: MaterialStateMouseCursor.clickable,
|
mouseCursor: MaterialStateMouseCursor.clickable,
|
||||||
visualDensity: VisualDensity.compact,
|
visualDensity: VisualDensity.compact,
|
||||||
|
isThreeLine: false,
|
||||||
child: const ListTile(),
|
child: const ListTile(),
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
@ -1098,6 +1106,217 @@ void main() {
|
|||||||
expect(theme.titleAlignment, ListTileTitleAlignment.top);
|
expect(theme.titleAlignment, ListTileTitleAlignment.top);
|
||||||
expect(theme.mouseCursor, MaterialStateMouseCursor.clickable);
|
expect(theme.mouseCursor, MaterialStateMouseCursor.clickable);
|
||||||
expect(theme.visualDensity, VisualDensity.compact);
|
expect(theme.visualDensity, VisualDensity.compact);
|
||||||
|
expect(theme.isThreeLine, false);
|
||||||
|
});
|
||||||
|
|
||||||
|
// Regression test for https://github.com/flutter/flutter/issues/165453
|
||||||
|
testWidgets('ListTileThemeData isThreeLine', (WidgetTester tester) async {
|
||||||
|
const double height = 300;
|
||||||
|
const double avatarTop = 130.0;
|
||||||
|
const double placeholderTop = 138.0;
|
||||||
|
|
||||||
|
Widget buildFrame({bool? isThreeLine}) {
|
||||||
|
return MaterialApp(
|
||||||
|
key: UniqueKey(),
|
||||||
|
theme:
|
||||||
|
isThreeLine != null
|
||||||
|
? ThemeData(listTileTheme: ListTileThemeData(isThreeLine: isThreeLine))
|
||||||
|
: null,
|
||||||
|
home: Material(
|
||||||
|
child: ListView(
|
||||||
|
children: const <Widget>[
|
||||||
|
ListTile(
|
||||||
|
leading: CircleAvatar(),
|
||||||
|
trailing: SizedBox(height: 24.0, width: 24.0, child: Placeholder()),
|
||||||
|
title: Text('A'),
|
||||||
|
subtitle: Text('A\nB\nC\nD\nE\nF\nG\nH\nI\nJ\nK\nL\nM'),
|
||||||
|
),
|
||||||
|
ListTile(
|
||||||
|
leading: CircleAvatar(),
|
||||||
|
trailing: SizedBox(height: 24.0, width: 24.0, child: Placeholder()),
|
||||||
|
title: Text('A'),
|
||||||
|
subtitle: Text('A'),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
void expectTwoLine() {
|
||||||
|
expect(
|
||||||
|
tester.getRect(find.byType(ListTile).at(0)),
|
||||||
|
const Rect.fromLTWH(0.0, 0.0, 800.0, height),
|
||||||
|
);
|
||||||
|
expect(
|
||||||
|
tester.getRect(find.byType(CircleAvatar).at(0)),
|
||||||
|
const Rect.fromLTWH(16.0, avatarTop, 40.0, 40.0),
|
||||||
|
);
|
||||||
|
expect(
|
||||||
|
tester.getRect(find.byType(Placeholder).at(0)),
|
||||||
|
const Rect.fromLTWH(800.0 - 24.0 - 24.0, placeholderTop, 24.0, 24.0),
|
||||||
|
);
|
||||||
|
expect(
|
||||||
|
tester.getRect(find.byType(ListTile).at(1)),
|
||||||
|
const Rect.fromLTWH(0.0, height, 800.0, 72.0),
|
||||||
|
);
|
||||||
|
expect(
|
||||||
|
tester.getRect(find.byType(CircleAvatar).at(1)),
|
||||||
|
const Rect.fromLTWH(16.0, height + 16.0, 40.0, 40.0),
|
||||||
|
);
|
||||||
|
expect(
|
||||||
|
tester.getRect(find.byType(Placeholder).at(1)),
|
||||||
|
const Rect.fromLTWH(800.0 - 24.0 - 24.0, height + 24.0, 24.0, 24.0),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
void expectThreeLine() {
|
||||||
|
expect(
|
||||||
|
tester.getRect(find.byType(ListTile).at(0)),
|
||||||
|
const Rect.fromLTWH(0.0, 0.0, 800.0, height),
|
||||||
|
);
|
||||||
|
expect(
|
||||||
|
tester.getRect(find.byType(CircleAvatar).at(0)),
|
||||||
|
const Rect.fromLTWH(16.0, 8.0, 40.0, 40.0),
|
||||||
|
);
|
||||||
|
expect(
|
||||||
|
tester.getRect(find.byType(Placeholder).at(0)),
|
||||||
|
const Rect.fromLTWH(800.0 - 24.0 - 24.0, 8.0, 24.0, 24.0),
|
||||||
|
);
|
||||||
|
expect(
|
||||||
|
tester.getRect(find.byType(ListTile).at(1)),
|
||||||
|
const Rect.fromLTWH(0.0, height, 800.0, 88.0),
|
||||||
|
);
|
||||||
|
expect(
|
||||||
|
tester.getRect(find.byType(CircleAvatar).at(1)),
|
||||||
|
const Rect.fromLTWH(16.0, height + 8.0, 40.0, 40.0),
|
||||||
|
);
|
||||||
|
expect(
|
||||||
|
tester.getRect(find.byType(Placeholder).at(1)),
|
||||||
|
const Rect.fromLTWH(800.0 - 24.0 - 24.0, height + 8.0, 24.0, 24.0),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
await tester.pumpWidget(buildFrame());
|
||||||
|
expectTwoLine();
|
||||||
|
|
||||||
|
await tester.pumpWidget(buildFrame(isThreeLine: false));
|
||||||
|
expectTwoLine();
|
||||||
|
|
||||||
|
await tester.pumpWidget(buildFrame(isThreeLine: true));
|
||||||
|
expectThreeLine();
|
||||||
|
});
|
||||||
|
|
||||||
|
// Regression test for https://github.com/flutter/flutter/issues/165453
|
||||||
|
testWidgets('ListTileTheme isThreeLine', (WidgetTester tester) async {
|
||||||
|
const double height = 300;
|
||||||
|
const double avatarTop = 130.0;
|
||||||
|
const double placeholderTop = 138.0;
|
||||||
|
|
||||||
|
await tester.pumpWidget(
|
||||||
|
MaterialApp(
|
||||||
|
theme: ThemeData(listTileTheme: const ListTileThemeData(isThreeLine: true)),
|
||||||
|
home: Material(
|
||||||
|
child: ListTileTheme(
|
||||||
|
data: const ListTileThemeData(isThreeLine: false),
|
||||||
|
child: ListView(
|
||||||
|
children: const <Widget>[
|
||||||
|
ListTile(
|
||||||
|
leading: CircleAvatar(),
|
||||||
|
trailing: SizedBox(height: 24.0, width: 24.0, child: Placeholder()),
|
||||||
|
title: Text('A'),
|
||||||
|
subtitle: Text('A\nB\nC\nD\nE\nF\nG\nH\nI\nJ\nK\nL\nM'),
|
||||||
|
),
|
||||||
|
ListTile(
|
||||||
|
leading: CircleAvatar(),
|
||||||
|
trailing: SizedBox(height: 24.0, width: 24.0, child: Placeholder()),
|
||||||
|
title: Text('A'),
|
||||||
|
subtitle: Text('A'),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(
|
||||||
|
tester.getRect(find.byType(ListTile).at(0)),
|
||||||
|
const Rect.fromLTWH(0.0, 0.0, 800.0, height),
|
||||||
|
);
|
||||||
|
expect(
|
||||||
|
tester.getRect(find.byType(CircleAvatar).at(0)),
|
||||||
|
const Rect.fromLTWH(16.0, avatarTop, 40.0, 40.0),
|
||||||
|
);
|
||||||
|
expect(
|
||||||
|
tester.getRect(find.byType(Placeholder).at(0)),
|
||||||
|
const Rect.fromLTWH(800.0 - 24.0 - 24.0, placeholderTop, 24.0, 24.0),
|
||||||
|
);
|
||||||
|
expect(
|
||||||
|
tester.getRect(find.byType(ListTile).at(1)),
|
||||||
|
const Rect.fromLTWH(0.0, height, 800.0, 72.0),
|
||||||
|
);
|
||||||
|
expect(
|
||||||
|
tester.getRect(find.byType(CircleAvatar).at(1)),
|
||||||
|
const Rect.fromLTWH(16.0, height + 16.0, 40.0, 40.0),
|
||||||
|
);
|
||||||
|
expect(
|
||||||
|
tester.getRect(find.byType(Placeholder).at(1)),
|
||||||
|
const Rect.fromLTWH(800.0 - 24.0 - 24.0, height + 24.0, 24.0, 24.0),
|
||||||
|
);
|
||||||
|
|
||||||
|
// THREE-LINE
|
||||||
|
await tester.pumpWidget(
|
||||||
|
MaterialApp(
|
||||||
|
key: UniqueKey(),
|
||||||
|
home: Material(
|
||||||
|
child: ListTileTheme(
|
||||||
|
data: const ListTileThemeData(isThreeLine: true),
|
||||||
|
child: ListView(
|
||||||
|
children: const <Widget>[
|
||||||
|
ListTile(
|
||||||
|
leading: CircleAvatar(),
|
||||||
|
trailing: SizedBox(height: 24.0, width: 24.0, child: Placeholder()),
|
||||||
|
title: Text('A'),
|
||||||
|
subtitle: Text('A\nB\nC\nD\nE\nF\nG\nH\nI\nJ\nK\nL\nM'),
|
||||||
|
),
|
||||||
|
ListTile(
|
||||||
|
leading: CircleAvatar(),
|
||||||
|
trailing: SizedBox(height: 24.0, width: 24.0, child: Placeholder()),
|
||||||
|
title: Text('A'),
|
||||||
|
subtitle: Text('A'),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(
|
||||||
|
tester.getRect(find.byType(ListTile).at(0)),
|
||||||
|
const Rect.fromLTWH(0.0, 0.0, 800.0, height),
|
||||||
|
);
|
||||||
|
expect(
|
||||||
|
tester.getRect(find.byType(CircleAvatar).at(0)),
|
||||||
|
const Rect.fromLTWH(16.0, 8.0, 40.0, 40.0),
|
||||||
|
);
|
||||||
|
expect(
|
||||||
|
tester.getRect(find.byType(Placeholder).at(0)),
|
||||||
|
const Rect.fromLTWH(800.0 - 24.0 - 24.0, 8.0, 24.0, 24.0),
|
||||||
|
);
|
||||||
|
expect(
|
||||||
|
tester.getRect(find.byType(ListTile).at(1)),
|
||||||
|
const Rect.fromLTWH(0.0, height, 800.0, 88.0),
|
||||||
|
);
|
||||||
|
expect(
|
||||||
|
tester.getRect(find.byType(CircleAvatar).at(1)),
|
||||||
|
const Rect.fromLTWH(16.0, height + 8.0, 40.0, 40.0),
|
||||||
|
);
|
||||||
|
expect(
|
||||||
|
tester.getRect(find.byType(Placeholder).at(1)),
|
||||||
|
const Rect.fromLTWH(800.0 - 24.0 - 24.0, height + 8.0, 24.0, 24.0),
|
||||||
|
);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user