Add ListTileControlAffinity
to ListTileTheme
(#150695)
fixes https://github.com/flutter/flutter/issues/146414 --- I saw @abikko submitted a PR https://github.com/flutter/flutter/pull/146630, but it was not completed due to CLA and lack of test cases. I am willing to complete this PR in combination with @abikko's code (I don't know if this is allowed) This PR adds contorlAffinity to ListTileTheme so that [CheckboxListTile], [RadioListTile], [SwitchListTile], and [ExpansionTile] can read and use it For example: If ListTileTheme in Theme sets contorlAffinity, then [CheckboxListTile] can directly use contorlAffinity in ListTileTheme. Of course, if contorlAffinity is also set in [CheckboxListTile], the property in [CheckboxListTile] will be used first.
This commit is contained in:
parent
e497ed7db0
commit
0a1d550e5f
@ -185,7 +185,7 @@ class CheckboxListTile extends StatelessWidget {
|
|||||||
this.dense,
|
this.dense,
|
||||||
this.secondary,
|
this.secondary,
|
||||||
this.selected = false,
|
this.selected = false,
|
||||||
this.controlAffinity = ListTileControlAffinity.platform,
|
this.controlAffinity,
|
||||||
this.contentPadding,
|
this.contentPadding,
|
||||||
this.tristate = false,
|
this.tristate = false,
|
||||||
this.checkboxShape,
|
this.checkboxShape,
|
||||||
@ -229,7 +229,7 @@ class CheckboxListTile extends StatelessWidget {
|
|||||||
this.dense,
|
this.dense,
|
||||||
this.secondary,
|
this.secondary,
|
||||||
this.selected = false,
|
this.selected = false,
|
||||||
this.controlAffinity = ListTileControlAffinity.platform,
|
this.controlAffinity,
|
||||||
this.contentPadding,
|
this.contentPadding,
|
||||||
this.tristate = false,
|
this.tristate = false,
|
||||||
this.checkboxShape,
|
this.checkboxShape,
|
||||||
@ -403,7 +403,7 @@ class CheckboxListTile extends StatelessWidget {
|
|||||||
final bool selected;
|
final bool selected;
|
||||||
|
|
||||||
/// Where to place the control relative to the text.
|
/// Where to place the control relative to the text.
|
||||||
final ListTileControlAffinity controlAffinity;
|
final ListTileControlAffinity? controlAffinity;
|
||||||
|
|
||||||
/// Defines insets surrounding the tile's contents.
|
/// Defines insets surrounding the tile's contents.
|
||||||
///
|
///
|
||||||
@ -518,10 +518,14 @@ class CheckboxListTile extends StatelessWidget {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
final (Widget? leading, Widget? trailing) = switch (controlAffinity) {
|
final ListTileThemeData listTileTheme = ListTileTheme.of(context);
|
||||||
|
final ListTileControlAffinity effectiveControlAffinity =
|
||||||
|
controlAffinity ?? listTileTheme.controlAffinity ?? ListTileControlAffinity.platform;
|
||||||
|
final (Widget? leading, Widget? trailing) = switch (effectiveControlAffinity) {
|
||||||
ListTileControlAffinity.leading => (control, secondary),
|
ListTileControlAffinity.leading => (control, secondary),
|
||||||
ListTileControlAffinity.trailing || ListTileControlAffinity.platform => (secondary, control),
|
ListTileControlAffinity.trailing || ListTileControlAffinity.platform => (secondary, control),
|
||||||
};
|
};
|
||||||
|
|
||||||
final ThemeData theme = Theme.of(context);
|
final ThemeData theme = Theme.of(context);
|
||||||
final CheckboxThemeData checkboxTheme = CheckboxTheme.of(context);
|
final CheckboxThemeData checkboxTheme = CheckboxTheme.of(context);
|
||||||
final Set<MaterialState> states = <MaterialState>{
|
final Set<MaterialState> states = <MaterialState>{
|
||||||
|
@ -660,8 +660,11 @@ class _ExpansionTileState extends State<ExpansionTile> with SingleTickerProvider
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Platform or null affinity defaults to trailing.
|
// Platform or null affinity defaults to trailing.
|
||||||
ListTileControlAffinity _effectiveAffinity(ListTileControlAffinity? affinity) {
|
ListTileControlAffinity _effectiveAffinity() {
|
||||||
switch (affinity ?? ListTileControlAffinity.trailing) {
|
final ListTileThemeData listTileTheme = ListTileTheme.of(context);
|
||||||
|
final ListTileControlAffinity affinity =
|
||||||
|
widget.controlAffinity ?? listTileTheme.controlAffinity ?? ListTileControlAffinity.trailing;
|
||||||
|
switch (affinity) {
|
||||||
case ListTileControlAffinity.leading:
|
case ListTileControlAffinity.leading:
|
||||||
return ListTileControlAffinity.leading;
|
return ListTileControlAffinity.leading;
|
||||||
case ListTileControlAffinity.trailing:
|
case ListTileControlAffinity.trailing:
|
||||||
@ -678,14 +681,14 @@ class _ExpansionTileState extends State<ExpansionTile> with SingleTickerProvider
|
|||||||
}
|
}
|
||||||
|
|
||||||
Widget? _buildLeadingIcon(BuildContext context) {
|
Widget? _buildLeadingIcon(BuildContext context) {
|
||||||
if (_effectiveAffinity(widget.controlAffinity) != ListTileControlAffinity.leading) {
|
if (_effectiveAffinity() != ListTileControlAffinity.leading) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
return _buildIcon(context);
|
return _buildIcon(context);
|
||||||
}
|
}
|
||||||
|
|
||||||
Widget? _buildTrailingIcon(BuildContext context) {
|
Widget? _buildTrailingIcon(BuildContext context) {
|
||||||
if (_effectiveAffinity(widget.controlAffinity) != ListTileControlAffinity.trailing) {
|
if (_effectiveAffinity() != ListTileControlAffinity.trailing) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
return _buildIcon(context);
|
return _buildIcon(context);
|
||||||
|
@ -65,6 +65,7 @@ class ListTileThemeData with Diagnosticable {
|
|||||||
this.visualDensity,
|
this.visualDensity,
|
||||||
this.minTileHeight,
|
this.minTileHeight,
|
||||||
this.titleAlignment,
|
this.titleAlignment,
|
||||||
|
this.controlAffinity,
|
||||||
});
|
});
|
||||||
|
|
||||||
/// Overrides the default value of [ListTile.dense].
|
/// Overrides the default value of [ListTile.dense].
|
||||||
@ -127,6 +128,10 @@ class ListTileThemeData with Diagnosticable {
|
|||||||
/// If specified, overrides the default value of [ListTile.titleAlignment].
|
/// If specified, overrides the default value of [ListTile.titleAlignment].
|
||||||
final ListTileTitleAlignment? titleAlignment;
|
final ListTileTitleAlignment? titleAlignment;
|
||||||
|
|
||||||
|
/// If specified, overrides the default value of [CheckboxListTile.controlAffinity]
|
||||||
|
/// or [ExpansionTile.controlAffinity] or [SwitchListTile.controlAffinity] or [RadioListTile.controlAffinity].
|
||||||
|
final ListTileControlAffinity? controlAffinity;
|
||||||
|
|
||||||
/// 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({
|
||||||
@ -151,6 +156,7 @@ class ListTileThemeData with Diagnosticable {
|
|||||||
bool? isThreeLine,
|
bool? isThreeLine,
|
||||||
VisualDensity? visualDensity,
|
VisualDensity? visualDensity,
|
||||||
ListTileTitleAlignment? titleAlignment,
|
ListTileTitleAlignment? titleAlignment,
|
||||||
|
ListTileControlAffinity? controlAffinity,
|
||||||
}) {
|
}) {
|
||||||
return ListTileThemeData(
|
return ListTileThemeData(
|
||||||
dense: dense ?? this.dense,
|
dense: dense ?? this.dense,
|
||||||
@ -173,6 +179,7 @@ class ListTileThemeData with Diagnosticable {
|
|||||||
mouseCursor: mouseCursor ?? this.mouseCursor,
|
mouseCursor: mouseCursor ?? this.mouseCursor,
|
||||||
visualDensity: visualDensity ?? this.visualDensity,
|
visualDensity: visualDensity ?? this.visualDensity,
|
||||||
titleAlignment: titleAlignment ?? this.titleAlignment,
|
titleAlignment: titleAlignment ?? this.titleAlignment,
|
||||||
|
controlAffinity: controlAffinity ?? this.controlAffinity,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -202,32 +209,36 @@ class ListTileThemeData with Diagnosticable {
|
|||||||
mouseCursor: t < 0.5 ? a?.mouseCursor : b?.mouseCursor,
|
mouseCursor: t < 0.5 ? a?.mouseCursor : b?.mouseCursor,
|
||||||
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,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
int get hashCode => Object.hash(
|
int get hashCode => Object.hashAll(
|
||||||
dense,
|
<Object?>[
|
||||||
shape,
|
dense,
|
||||||
style,
|
shape,
|
||||||
selectedColor,
|
style,
|
||||||
iconColor,
|
selectedColor,
|
||||||
textColor,
|
iconColor,
|
||||||
titleTextStyle,
|
textColor,
|
||||||
subtitleTextStyle,
|
titleTextStyle,
|
||||||
leadingAndTrailingTextStyle,
|
subtitleTextStyle,
|
||||||
contentPadding,
|
leadingAndTrailingTextStyle,
|
||||||
tileColor,
|
contentPadding,
|
||||||
selectedTileColor,
|
tileColor,
|
||||||
horizontalTitleGap,
|
selectedTileColor,
|
||||||
minVerticalPadding,
|
horizontalTitleGap,
|
||||||
minLeadingWidth,
|
minVerticalPadding,
|
||||||
minTileHeight,
|
minLeadingWidth,
|
||||||
enableFeedback,
|
minTileHeight,
|
||||||
mouseCursor,
|
enableFeedback,
|
||||||
visualDensity,
|
mouseCursor,
|
||||||
titleAlignment,
|
visualDensity,
|
||||||
);
|
titleAlignment,
|
||||||
|
controlAffinity,
|
||||||
|
],
|
||||||
|
);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
bool operator ==(Object other) {
|
bool operator ==(Object other) {
|
||||||
@ -257,7 +268,8 @@ class ListTileThemeData with Diagnosticable {
|
|||||||
&& other.enableFeedback == enableFeedback
|
&& other.enableFeedback == enableFeedback
|
||||||
&& other.mouseCursor == mouseCursor
|
&& other.mouseCursor == mouseCursor
|
||||||
&& other.visualDensity == visualDensity
|
&& other.visualDensity == visualDensity
|
||||||
&& other.titleAlignment == titleAlignment;
|
&& other.titleAlignment == titleAlignment
|
||||||
|
&& other.controlAffinity == controlAffinity;
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@ -283,6 +295,7 @@ class ListTileThemeData with Diagnosticable {
|
|||||||
properties.add(DiagnosticsProperty<MaterialStateProperty<MouseCursor?>>('mouseCursor', mouseCursor, defaultValue: null));
|
properties.add(DiagnosticsProperty<MaterialStateProperty<MouseCursor?>>('mouseCursor', mouseCursor, defaultValue: null));
|
||||||
properties.add(DiagnosticsProperty<VisualDensity>('visualDensity', visualDensity, defaultValue: null));
|
properties.add(DiagnosticsProperty<VisualDensity>('visualDensity', visualDensity, defaultValue: null));
|
||||||
properties.add(DiagnosticsProperty<ListTileTitleAlignment>('titleAlignment', titleAlignment, defaultValue: null));
|
properties.add(DiagnosticsProperty<ListTileTitleAlignment>('titleAlignment', titleAlignment, defaultValue: null));
|
||||||
|
properties.add(DiagnosticsProperty<ListTileControlAffinity>('controlAffinity', controlAffinity, defaultValue: null));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -317,6 +330,7 @@ class ListTileTheme extends InheritedTheme {
|
|||||||
double? horizontalTitleGap,
|
double? horizontalTitleGap,
|
||||||
double? minVerticalPadding,
|
double? minVerticalPadding,
|
||||||
double? minLeadingWidth,
|
double? minLeadingWidth,
|
||||||
|
ListTileControlAffinity? controlAffinity,
|
||||||
required super.child,
|
required super.child,
|
||||||
}) : assert(
|
}) : assert(
|
||||||
data == null ||
|
data == null ||
|
||||||
@ -331,7 +345,8 @@ class ListTileTheme extends InheritedTheme {
|
|||||||
mouseCursor ??
|
mouseCursor ??
|
||||||
horizontalTitleGap ??
|
horizontalTitleGap ??
|
||||||
minVerticalPadding ??
|
minVerticalPadding ??
|
||||||
minLeadingWidth) == null),
|
minLeadingWidth ??
|
||||||
|
controlAffinity) == null),
|
||||||
_data = data,
|
_data = data,
|
||||||
_dense = dense,
|
_dense = dense,
|
||||||
_shape = shape,
|
_shape = shape,
|
||||||
@ -346,7 +361,8 @@ class ListTileTheme extends InheritedTheme {
|
|||||||
_mouseCursor = mouseCursor,
|
_mouseCursor = mouseCursor,
|
||||||
_horizontalTitleGap = horizontalTitleGap,
|
_horizontalTitleGap = horizontalTitleGap,
|
||||||
_minVerticalPadding = minVerticalPadding,
|
_minVerticalPadding = minVerticalPadding,
|
||||||
_minLeadingWidth = minLeadingWidth;
|
_minLeadingWidth = minLeadingWidth,
|
||||||
|
_controlAffinity = controlAffinity;
|
||||||
|
|
||||||
final ListTileThemeData? _data;
|
final ListTileThemeData? _data;
|
||||||
final bool? _dense;
|
final bool? _dense;
|
||||||
@ -363,6 +379,7 @@ class ListTileTheme extends InheritedTheme {
|
|||||||
final double? _minLeadingWidth;
|
final double? _minLeadingWidth;
|
||||||
final bool? _enableFeedback;
|
final bool? _enableFeedback;
|
||||||
final MaterialStateProperty<MouseCursor?>? _mouseCursor;
|
final MaterialStateProperty<MouseCursor?>? _mouseCursor;
|
||||||
|
final ListTileControlAffinity? _controlAffinity;
|
||||||
|
|
||||||
/// The configuration of this theme.
|
/// The configuration of this theme.
|
||||||
ListTileThemeData get data {
|
ListTileThemeData get data {
|
||||||
@ -381,6 +398,7 @@ class ListTileTheme extends InheritedTheme {
|
|||||||
horizontalTitleGap: _horizontalTitleGap,
|
horizontalTitleGap: _horizontalTitleGap,
|
||||||
minVerticalPadding: _minVerticalPadding,
|
minVerticalPadding: _minVerticalPadding,
|
||||||
minLeadingWidth: _minLeadingWidth,
|
minLeadingWidth: _minLeadingWidth,
|
||||||
|
controlAffinity: _controlAffinity,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -462,6 +480,13 @@ class ListTileTheme extends InheritedTheme {
|
|||||||
/// [ListTileThemeData.enableFeedback] property instead.
|
/// [ListTileThemeData.enableFeedback] property instead.
|
||||||
bool? get enableFeedback => _data != null ? _data.enableFeedback : _enableFeedback;
|
bool? get enableFeedback => _data != null ? _data.enableFeedback : _enableFeedback;
|
||||||
|
|
||||||
|
/// Overrides the default value of [CheckboxListTile.controlAffinity]
|
||||||
|
/// or [ExpansionTile.controlAffinity] or [SwitchListTile.controlAffinity] or [RadioListTile.controlAffinity]
|
||||||
|
///
|
||||||
|
/// This property is obsolete: please use the
|
||||||
|
/// [ListTileThemeData.controlAffinity] property instead.
|
||||||
|
ListTileControlAffinity? get controlAffinity => _data != null ? _data.controlAffinity : _controlAffinity;
|
||||||
|
|
||||||
/// The [data] property of the closest instance of this class that
|
/// The [data] property of the closest instance of this class that
|
||||||
/// encloses the given context.
|
/// encloses the given context.
|
||||||
///
|
///
|
||||||
@ -502,6 +527,7 @@ class ListTileTheme extends InheritedTheme {
|
|||||||
ListTileTitleAlignment? titleAlignment,
|
ListTileTitleAlignment? titleAlignment,
|
||||||
MaterialStateProperty<MouseCursor?>? mouseCursor,
|
MaterialStateProperty<MouseCursor?>? mouseCursor,
|
||||||
VisualDensity? visualDensity,
|
VisualDensity? visualDensity,
|
||||||
|
ListTileControlAffinity? controlAffinity,
|
||||||
required Widget child,
|
required Widget child,
|
||||||
}) {
|
}) {
|
||||||
return Builder(
|
return Builder(
|
||||||
@ -530,6 +556,7 @@ class ListTileTheme extends InheritedTheme {
|
|||||||
titleAlignment: titleAlignment ?? parent.titleAlignment,
|
titleAlignment: titleAlignment ?? parent.titleAlignment,
|
||||||
mouseCursor: mouseCursor ?? parent.mouseCursor,
|
mouseCursor: mouseCursor ?? parent.mouseCursor,
|
||||||
visualDensity: visualDensity ?? parent.visualDensity,
|
visualDensity: visualDensity ?? parent.visualDensity,
|
||||||
|
controlAffinity: controlAffinity ?? parent.controlAffinity,
|
||||||
),
|
),
|
||||||
child: child,
|
child: child,
|
||||||
);
|
);
|
||||||
|
@ -178,7 +178,7 @@ class RadioListTile<T> extends StatelessWidget {
|
|||||||
this.dense,
|
this.dense,
|
||||||
this.secondary,
|
this.secondary,
|
||||||
this.selected = false,
|
this.selected = false,
|
||||||
this.controlAffinity = ListTileControlAffinity.platform,
|
this.controlAffinity,
|
||||||
this.autofocus = false,
|
this.autofocus = false,
|
||||||
this.contentPadding,
|
this.contentPadding,
|
||||||
this.shape,
|
this.shape,
|
||||||
@ -217,7 +217,7 @@ class RadioListTile<T> extends StatelessWidget {
|
|||||||
this.dense,
|
this.dense,
|
||||||
this.secondary,
|
this.secondary,
|
||||||
this.selected = false,
|
this.selected = false,
|
||||||
this.controlAffinity = ListTileControlAffinity.platform,
|
this.controlAffinity,
|
||||||
this.autofocus = false,
|
this.autofocus = false,
|
||||||
this.contentPadding,
|
this.contentPadding,
|
||||||
this.shape,
|
this.shape,
|
||||||
@ -389,7 +389,7 @@ class RadioListTile<T> extends StatelessWidget {
|
|||||||
final bool selected;
|
final bool selected;
|
||||||
|
|
||||||
/// Where to place the control relative to the text.
|
/// Where to place the control relative to the text.
|
||||||
final ListTileControlAffinity controlAffinity;
|
final ListTileControlAffinity? controlAffinity;
|
||||||
|
|
||||||
/// {@macro flutter.widgets.Focus.autofocus}
|
/// {@macro flutter.widgets.Focus.autofocus}
|
||||||
final bool autofocus;
|
final bool autofocus;
|
||||||
@ -488,11 +488,15 @@ class RadioListTile<T> extends StatelessWidget {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
final ListTileThemeData listTileTheme = ListTileTheme.of(context);
|
||||||
|
final ListTileControlAffinity effectiveControlAffinity =
|
||||||
|
controlAffinity ?? listTileTheme.controlAffinity ?? ListTileControlAffinity.platform;
|
||||||
Widget? leading, trailing;
|
Widget? leading, trailing;
|
||||||
(leading, trailing) = switch (controlAffinity) {
|
(leading, trailing) = switch (effectiveControlAffinity) {
|
||||||
ListTileControlAffinity.leading || ListTileControlAffinity.platform => (control, secondary),
|
ListTileControlAffinity.leading || ListTileControlAffinity.platform => (control, secondary),
|
||||||
ListTileControlAffinity.trailing => (secondary, control),
|
ListTileControlAffinity.trailing => (secondary, control),
|
||||||
};
|
};
|
||||||
|
|
||||||
final ThemeData theme = Theme.of(context);
|
final ThemeData theme = Theme.of(context);
|
||||||
final RadioThemeData radioThemeData = RadioTheme.of(context);
|
final RadioThemeData radioThemeData = RadioTheme.of(context);
|
||||||
final Set<MaterialState> states = <MaterialState>{
|
final Set<MaterialState> states = <MaterialState>{
|
||||||
|
@ -192,7 +192,7 @@ class SwitchListTile extends StatelessWidget {
|
|||||||
this.contentPadding,
|
this.contentPadding,
|
||||||
this.secondary,
|
this.secondary,
|
||||||
this.selected = false,
|
this.selected = false,
|
||||||
this.controlAffinity = ListTileControlAffinity.platform,
|
this.controlAffinity,
|
||||||
this.shape,
|
this.shape,
|
||||||
this.selectedTileColor,
|
this.selectedTileColor,
|
||||||
this.visualDensity,
|
this.visualDensity,
|
||||||
@ -249,7 +249,7 @@ class SwitchListTile extends StatelessWidget {
|
|||||||
this.contentPadding,
|
this.contentPadding,
|
||||||
this.secondary,
|
this.secondary,
|
||||||
this.selected = false,
|
this.selected = false,
|
||||||
this.controlAffinity = ListTileControlAffinity.platform,
|
this.controlAffinity,
|
||||||
this.shape,
|
this.shape,
|
||||||
this.selectedTileColor,
|
this.selectedTileColor,
|
||||||
this.visualDensity,
|
this.visualDensity,
|
||||||
@ -480,7 +480,7 @@ class SwitchListTile extends StatelessWidget {
|
|||||||
/// Defines the position of control and [secondary], relative to text.
|
/// Defines the position of control and [secondary], relative to text.
|
||||||
///
|
///
|
||||||
/// By default, the value of [controlAffinity] is [ListTileControlAffinity.platform].
|
/// By default, the value of [controlAffinity] is [ListTileControlAffinity.platform].
|
||||||
final ListTileControlAffinity controlAffinity;
|
final ListTileControlAffinity? controlAffinity;
|
||||||
|
|
||||||
/// {@macro flutter.material.ListTile.shape}
|
/// {@macro flutter.material.ListTile.shape}
|
||||||
final ShapeBorder? shape;
|
final ShapeBorder? shape;
|
||||||
@ -566,8 +566,11 @@ class SwitchListTile extends StatelessWidget {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
final ListTileThemeData listTileTheme = ListTileTheme.of(context);
|
||||||
|
final ListTileControlAffinity effectiveControlAffinity =
|
||||||
|
controlAffinity ?? listTileTheme.controlAffinity ?? ListTileControlAffinity.platform;
|
||||||
Widget? leading, trailing;
|
Widget? leading, trailing;
|
||||||
(leading, trailing) = switch (controlAffinity) {
|
(leading, trailing) = switch (effectiveControlAffinity) {
|
||||||
ListTileControlAffinity.leading => (control, secondary),
|
ListTileControlAffinity.leading => (control, secondary),
|
||||||
ListTileControlAffinity.trailing || ListTileControlAffinity.platform => (secondary, control),
|
ListTileControlAffinity.trailing || ListTileControlAffinity.platform => (secondary, control),
|
||||||
};
|
};
|
||||||
|
@ -1231,6 +1231,39 @@ void main() {
|
|||||||
expect(Focus.of(firstChildKey.currentContext!).hasPrimaryFocus, isFalse);
|
expect(Focus.of(firstChildKey.currentContext!).hasPrimaryFocus, isFalse);
|
||||||
expect(Focus.of(secondChildKey.currentContext!).hasPrimaryFocus, isTrue);
|
expect(Focus.of(secondChildKey.currentContext!).hasPrimaryFocus, isTrue);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
testWidgets('CheckboxListTile uses ListTileTheme controlAffinity', (WidgetTester tester) async {
|
||||||
|
Widget buildListTile(ListTileControlAffinity controlAffinity) {
|
||||||
|
return MaterialApp(
|
||||||
|
home: Material(
|
||||||
|
child: ListTileTheme(
|
||||||
|
data: ListTileThemeData(
|
||||||
|
controlAffinity: controlAffinity,
|
||||||
|
),
|
||||||
|
child: CheckboxListTile(
|
||||||
|
value: false,
|
||||||
|
onChanged: (bool? value) {},
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
await tester.pumpWidget(buildListTile(ListTileControlAffinity.trailing));
|
||||||
|
final Finder trailing = find.byType(Checkbox);
|
||||||
|
final Offset offsetTrailing = tester.getTopLeft(trailing);
|
||||||
|
expect(offsetTrailing, const Offset(736.0, 8.0));
|
||||||
|
|
||||||
|
await tester.pumpWidget(buildListTile(ListTileControlAffinity.leading));
|
||||||
|
final Finder leading = find.byType(Checkbox);
|
||||||
|
final Offset offsetLeading = tester.getTopLeft(leading);
|
||||||
|
expect(offsetLeading, const Offset(16.0, 8.0));
|
||||||
|
|
||||||
|
await tester.pumpWidget(buildListTile(ListTileControlAffinity.platform));
|
||||||
|
final Finder platform = find.byType(Checkbox);
|
||||||
|
final Offset offsetPlatform = tester.getTopLeft(platform);
|
||||||
|
expect(offsetPlatform, const Offset(736.0, 8.0));
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
class _SelectedGrabMouseCursor extends MaterialStateMouseCursor {
|
class _SelectedGrabMouseCursor extends MaterialStateMouseCursor {
|
||||||
|
@ -1585,4 +1585,36 @@ void main() {
|
|||||||
|
|
||||||
expect(titleSize.width, materialAppSize.width - 32.0);
|
expect(titleSize.width, materialAppSize.width - 32.0);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
testWidgets('ExpansionTile uses ListTileTheme controlAffinity', (WidgetTester tester) async {
|
||||||
|
Widget buildView(ListTileControlAffinity controlAffinity) {
|
||||||
|
return MaterialApp(
|
||||||
|
home: ListTileTheme(
|
||||||
|
data: ListTileThemeData(
|
||||||
|
controlAffinity: controlAffinity,
|
||||||
|
),
|
||||||
|
child: const Material(
|
||||||
|
child: ExpansionTile(
|
||||||
|
title: Text('ExpansionTile'),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
await tester.pumpWidget(buildView(ListTileControlAffinity.leading));
|
||||||
|
final Finder leading = find.text('ExpansionTile');
|
||||||
|
final Offset offsetLeading = tester.getTopLeft(leading);
|
||||||
|
expect(offsetLeading, const Offset(56.0, 17.0));
|
||||||
|
|
||||||
|
await tester.pumpWidget(buildView(ListTileControlAffinity.trailing));
|
||||||
|
final Finder trailing = find.text('ExpansionTile');
|
||||||
|
final Offset offsetTrailing = tester.getTopLeft(trailing);
|
||||||
|
expect(offsetTrailing, const Offset(16.0, 17.0));
|
||||||
|
|
||||||
|
await tester.pumpWidget(buildView(ListTileControlAffinity.platform));
|
||||||
|
final Finder platform = find.text('ExpansionTile');
|
||||||
|
final Offset offsetPlatform = tester.getTopLeft(platform);
|
||||||
|
expect(offsetPlatform, const Offset(16.0, 17.0));
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
@ -1547,4 +1547,39 @@ void main() {
|
|||||||
);
|
);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
testWidgets('RadioListTile uses ListTileTheme controlAffinity', (WidgetTester tester) async {
|
||||||
|
Widget buildListTile(ListTileControlAffinity controlAffinity) {
|
||||||
|
return MaterialApp(
|
||||||
|
home: Material(
|
||||||
|
child: ListTileTheme(
|
||||||
|
data: ListTileThemeData(
|
||||||
|
controlAffinity: controlAffinity,
|
||||||
|
),
|
||||||
|
child: RadioListTile<double>(
|
||||||
|
value: 0.5,
|
||||||
|
groupValue: 1.0,
|
||||||
|
title: const Text('RadioListTile'),
|
||||||
|
onChanged: (double? value) {},
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
await tester.pumpWidget(buildListTile(ListTileControlAffinity.leading));
|
||||||
|
final Finder leading = find.text('RadioListTile');
|
||||||
|
final Offset offsetLeading = tester.getTopLeft(leading);
|
||||||
|
expect(offsetLeading, const Offset(72.0, 16.0));
|
||||||
|
|
||||||
|
await tester.pumpWidget(buildListTile(ListTileControlAffinity.trailing));
|
||||||
|
final Finder trailing = find.text('RadioListTile');
|
||||||
|
final Offset offsetTrailing = tester.getTopLeft(trailing);
|
||||||
|
expect(offsetTrailing, const Offset(16.0, 16.0));
|
||||||
|
|
||||||
|
await tester.pumpWidget(buildListTile(ListTileControlAffinity.platform));
|
||||||
|
final Finder platform = find.text('RadioListTile');
|
||||||
|
final Offset offsetPlatform = tester.getTopLeft(platform);
|
||||||
|
expect(offsetPlatform, const Offset(72.0, 16.0));
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
@ -1691,4 +1691,38 @@ void main() {
|
|||||||
expect(Focus.of(firstChildKey.currentContext!).hasPrimaryFocus, isFalse);
|
expect(Focus.of(firstChildKey.currentContext!).hasPrimaryFocus, isFalse);
|
||||||
expect(Focus.of(secondChildKey.currentContext!).hasPrimaryFocus, isTrue);
|
expect(Focus.of(secondChildKey.currentContext!).hasPrimaryFocus, isTrue);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
testWidgets('SwitchListTile uses ListTileTheme controlAffinity', (WidgetTester tester) async {
|
||||||
|
Widget buildView(ListTileControlAffinity controlAffinity) {
|
||||||
|
return MaterialApp(
|
||||||
|
home: Material(
|
||||||
|
child: ListTileTheme(
|
||||||
|
data: ListTileThemeData(
|
||||||
|
controlAffinity: controlAffinity,
|
||||||
|
),
|
||||||
|
child: SwitchListTile(
|
||||||
|
value: true,
|
||||||
|
title: const Text('SwitchListTile'),
|
||||||
|
onChanged: (bool value) {},
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
await tester.pumpWidget(buildView(ListTileControlAffinity.leading));
|
||||||
|
final Finder leading = find.text('SwitchListTile');
|
||||||
|
final Offset offsetLeading = tester.getTopLeft(leading);
|
||||||
|
expect(offsetLeading, const Offset(92.0, 16.0));
|
||||||
|
|
||||||
|
await tester.pumpWidget(buildView(ListTileControlAffinity.trailing));
|
||||||
|
final Finder trailing = find.text('SwitchListTile');
|
||||||
|
final Offset offsetTrailing = tester.getTopLeft(trailing);
|
||||||
|
expect(offsetTrailing, const Offset(16.0, 16.0));
|
||||||
|
|
||||||
|
await tester.pumpWidget(buildView(ListTileControlAffinity.platform));
|
||||||
|
final Finder platform = find.text('SwitchListTile');
|
||||||
|
final Offset offsetPlatform = tester.getTopLeft(platform);
|
||||||
|
expect(offsetPlatform, const Offset(16.0, 16.0));
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user