Switch list tile adaptive (#24437)

* SwitchListTile.adaptive for wrapping an adaptive Switch

* Test SwitchListTile.adaptive same as Switch.adaptive

* Remove TODO

* Comment and switch statement cleanup
This commit is contained in:
Justin McCandless 2018-11-16 14:50:17 -08:00 committed by GitHub
parent 265485033b
commit a8552ca7ec
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 117 additions and 12 deletions

View file

@ -13,6 +13,8 @@ import 'theme_data.dart';
// void setState(VoidCallback fn) { }
// bool _lights;
enum _SwitchListTileType { material, adaptive }
/// A [ListTile] with a [Switch]. In other words, a switch with a label.
///
/// The entire list tile is interactive: tapping anywhere in the tile toggles
@ -90,7 +92,39 @@ class SwitchListTile extends StatelessWidget {
this.dense,
this.secondary,
this.selected = false,
}) : assert(value != null),
}) : _switchListTileType = _SwitchListTileType.material,
assert(value != null),
assert(isThreeLine != null),
assert(!isThreeLine || subtitle != null),
assert(selected != null),
super(key: key);
/// Creates the wrapped switch with [Switch.adaptive].
///
/// Creates a [CupertinoSwitch] if the target platform is iOS, creates a
/// material design switch otherwise.
///
/// If a [CupertinoSwitch] is created, the following parameters are
/// ignored: [activeTrackColor], [inactiveThumbColor], [inactiveTrackColor],
/// [activeThumbImage], [inactiveThumbImage], [materialTapTargetSize].
const SwitchListTile.adaptive({
Key key,
@required this.value,
@required this.onChanged,
this.activeColor,
this.activeTrackColor,
this.inactiveThumbColor,
this.inactiveTrackColor,
this.activeThumbImage,
this.inactiveThumbImage,
this.title,
this.subtitle,
this.isThreeLine = false,
this.dense,
this.secondary,
this.selected = false,
}) : _switchListTileType = _SwitchListTileType.adaptive,
assert(value != null),
assert(isThreeLine != null),
assert(!isThreeLine || subtitle != null),
assert(selected != null),
@ -134,22 +168,30 @@ class SwitchListTile extends StatelessWidget {
/// The color to use on the track when this switch is on.
///
/// Defaults to [ThemeData.toggleableActiveColor] with the opacity set at 50%.
///
/// Ignored if created with [SwitchListTile.adaptive].
final Color activeTrackColor;
/// The color to use on the thumb when this switch is off.
///
/// Defaults to the colors described in the Material design specification.
///
/// Ignored if created with [SwitchListTile.adaptive].
final Color inactiveThumbColor;
/// The color to use on the track when this switch is off.
///
/// Defaults to the colors described in the Material design specification.
///
/// Ignored if created with [SwitchListTile.adaptive].
final Color inactiveTrackColor;
/// An image to use on the thumb of this switch when the switch is on.
final ImageProvider activeThumbImage;
/// An image to use on the thumb of this switch when the switch is off.
///
/// Ignored if created with [SwitchListTile.adaptive].
final ImageProvider inactiveThumbImage;
/// The primary content of the list tile.
@ -187,19 +229,40 @@ class SwitchListTile extends StatelessWidget {
/// Normally, this property is left to its default value, false.
final bool selected;
/// If adaptive, creates the switch with [Switch.adaptive].
final _SwitchListTileType _switchListTileType;
@override
Widget build(BuildContext context) {
final Widget control = Switch(
value: value,
onChanged: onChanged,
activeColor: activeColor,
activeThumbImage: activeThumbImage,
inactiveThumbImage: inactiveThumbImage,
materialTapTargetSize: MaterialTapTargetSize.shrinkWrap,
activeTrackColor: activeTrackColor,
inactiveTrackColor: inactiveTrackColor,
inactiveThumbColor: inactiveThumbColor,
);
Widget control;
switch (_switchListTileType) {
case _SwitchListTileType.adaptive:
control = Switch.adaptive(
value: value,
onChanged: onChanged,
activeColor: activeColor,
activeThumbImage: activeThumbImage,
inactiveThumbImage: inactiveThumbImage,
materialTapTargetSize: MaterialTapTargetSize.shrinkWrap,
activeTrackColor: activeTrackColor,
inactiveTrackColor: inactiveTrackColor,
inactiveThumbColor: inactiveThumbColor,
);
break;
case _SwitchListTileType.material:
control = Switch(
value: value,
onChanged: onChanged,
activeColor: activeColor,
activeThumbImage: activeThumbImage,
inactiveThumbImage: inactiveThumbImage,
materialTapTargetSize: MaterialTapTargetSize.shrinkWrap,
activeTrackColor: activeTrackColor,
inactiveTrackColor: inactiveTrackColor,
inactiveThumbColor: inactiveThumbColor,
);
}
return MergeSemantics(
child: ListTileTheme.merge(
selectedColor: activeColor ?? Theme.of(context).accentColor,

View file

@ -2,6 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter_test/flutter_test.dart';
import '../rendering/mock_canvas.dart';
@ -58,4 +59,45 @@ void main() {
..circle(color: Colors.red[500])
);
});
testWidgets('SwitchListTile.adaptive delegates to', (WidgetTester tester) async {
bool value = false;
Widget buildFrame(TargetPlatform platform) {
return MaterialApp(
theme: ThemeData(platform: platform),
home: StatefulBuilder(
builder: (BuildContext context, StateSetter setState) {
return Material(
child: Center(
child: SwitchListTile.adaptive(
value: value,
onChanged: (bool newValue) {
setState(() {
value = newValue;
});
},
),
),
);
},
),
);
}
await tester.pumpWidget(buildFrame(TargetPlatform.iOS));
expect(find.byType(CupertinoSwitch), findsOneWidget);
expect(value, isFalse);
await tester.tap(find.byType(SwitchListTile));
expect(value, isTrue);
await tester.pumpWidget(buildFrame(TargetPlatform.android));
await tester.pumpAndSettle(); // Finish the theme change animation.
expect(find.byType(CupertinoSwitch), findsNothing);
expect(value, isTrue);
await tester.tap(find.byType(SwitchListTile));
expect(value, isFalse);
});
}