mirror of
https://github.com/flutter/flutter.git
synced 2025-06-03 00:51:18 +00:00
Migrated Switch
to Material 3 (#110095)
This commit is contained in:
parent
e3f8ee8806
commit
75fac6ae4d
@ -31,6 +31,7 @@ import 'package:gen_defaults/input_decorator_template.dart';
|
||||
import 'package:gen_defaults/navigation_bar_template.dart';
|
||||
import 'package:gen_defaults/navigation_rail_template.dart';
|
||||
import 'package:gen_defaults/surface_tint.dart';
|
||||
import 'package:gen_defaults/switch_template.dart';
|
||||
import 'package:gen_defaults/text_field_template.dart';
|
||||
import 'package:gen_defaults/typography_template.dart';
|
||||
|
||||
@ -121,6 +122,7 @@ Future<void> main(List<String> args) async {
|
||||
NavigationBarTemplate('NavigationBar', '$materialLib/navigation_bar.dart', tokens).updateFile();
|
||||
NavigationRailTemplate('NavigationRail', '$materialLib/navigation_rail.dart', tokens).updateFile();
|
||||
SurfaceTintTemplate('SurfaceTint', '$materialLib/elevation_overlay.dart', tokens).updateFile();
|
||||
SwitchTemplate('Switch', '$materialLib/switch.dart', tokens).updateFile();
|
||||
TextFieldTemplate('TextField', '$materialLib/text_field.dart', tokens).updateFile();
|
||||
TypographyTemplate('Typography', '$materialLib/typography.dart', tokens).updateFile();
|
||||
}
|
||||
|
208
dev/tools/gen_defaults/lib/switch_template.dart
Normal file
208
dev/tools/gen_defaults/lib/switch_template.dart
Normal file
@ -0,0 +1,208 @@
|
||||
// Copyright 2014 The Flutter Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
import 'template.dart';
|
||||
|
||||
class SwitchTemplate extends TokenTemplate {
|
||||
const SwitchTemplate(super.blockName, super.fileName, super.tokens, {
|
||||
super.colorSchemePrefix = '_colors.',
|
||||
});
|
||||
|
||||
@override
|
||||
String generate() => '''
|
||||
class _${blockName}DefaultsM3 extends SwitchThemeData {
|
||||
_${blockName}DefaultsM3(BuildContext context)
|
||||
: _colors = Theme.of(context).colorScheme;
|
||||
|
||||
final ColorScheme _colors;
|
||||
|
||||
@override
|
||||
MaterialStateProperty<Color> get thumbColor {
|
||||
return MaterialStateProperty.resolveWith((Set<MaterialState> states) {
|
||||
if (states.contains(MaterialState.disabled)) {
|
||||
if (states.contains(MaterialState.selected)) {
|
||||
return ${componentColor('md.comp.switch.disabled.selected.handle')};
|
||||
}
|
||||
return ${componentColor('md.comp.switch.disabled.unselected.handle')};
|
||||
}
|
||||
if (states.contains(MaterialState.selected)) {
|
||||
if (states.contains(MaterialState.pressed)) {
|
||||
return ${componentColor('md.comp.switch.selected.pressed.handle')};
|
||||
}
|
||||
if (states.contains(MaterialState.hovered)) {
|
||||
return ${componentColor('md.comp.switch.selected.hover.handle')};
|
||||
}
|
||||
if (states.contains(MaterialState.focused)) {
|
||||
return ${componentColor('md.comp.switch.selected.focus.handle')};
|
||||
}
|
||||
return ${componentColor('md.comp.switch.selected.handle')};
|
||||
}
|
||||
if (states.contains(MaterialState.pressed)) {
|
||||
return ${componentColor('md.comp.switch.unselected.pressed.handle')};
|
||||
}
|
||||
if (states.contains(MaterialState.hovered)) {
|
||||
return ${componentColor('md.comp.switch.unselected.hover.handle')};
|
||||
}
|
||||
if (states.contains(MaterialState.focused)) {
|
||||
return ${componentColor('md.comp.switch.unselected.focus.handle')};
|
||||
}
|
||||
return ${componentColor('md.comp.switch.unselected.handle')};
|
||||
});
|
||||
}
|
||||
|
||||
@override
|
||||
MaterialStateProperty<Color> get trackColor {
|
||||
return MaterialStateProperty.resolveWith((Set<MaterialState> states) {
|
||||
if (states.contains(MaterialState.disabled)) {
|
||||
if (states.contains(MaterialState.selected)) {
|
||||
return ${componentColor('md.comp.switch.disabled.selected.track')}.withOpacity(${opacity('md.comp.switch.disabled.track.opacity')});
|
||||
}
|
||||
return ${componentColor('md.comp.switch.disabled.unselected.track')}.withOpacity(${opacity('md.comp.switch.disabled.track.opacity')});
|
||||
}
|
||||
if (states.contains(MaterialState.selected)) {
|
||||
if (states.contains(MaterialState.pressed)) {
|
||||
return ${componentColor('md.comp.switch.selected.pressed.track')};
|
||||
}
|
||||
if (states.contains(MaterialState.hovered)) {
|
||||
return ${componentColor('md.comp.switch.selected.hover.track')};
|
||||
}
|
||||
if (states.contains(MaterialState.focused)) {
|
||||
return ${componentColor('md.comp.switch.selected.focus.track')};
|
||||
}
|
||||
return ${componentColor('md.comp.switch.selected.track')};
|
||||
}
|
||||
if (states.contains(MaterialState.pressed)) {
|
||||
return ${componentColor('md.comp.switch.unselected.pressed.track')};
|
||||
}
|
||||
if (states.contains(MaterialState.hovered)) {
|
||||
return ${componentColor('md.comp.switch.unselected.hover.track')};
|
||||
}
|
||||
if (states.contains(MaterialState.focused)) {
|
||||
return ${componentColor('md.comp.switch.unselected.focus.track')};
|
||||
}
|
||||
return ${componentColor('md.comp.switch.unselected.track')};
|
||||
});
|
||||
}
|
||||
|
||||
@override
|
||||
MaterialStateProperty<Color?> get overlayColor {
|
||||
return MaterialStateProperty.resolveWith((Set<MaterialState> states) {
|
||||
if (states.contains(MaterialState.selected)) {
|
||||
if (states.contains(MaterialState.pressed)) {
|
||||
return ${componentColor('md.comp.switch.selected.pressed.state-layer')};
|
||||
}
|
||||
if (states.contains(MaterialState.hovered)) {
|
||||
return ${componentColor('md.comp.switch.selected.hover.state-layer')};
|
||||
}
|
||||
if (states.contains(MaterialState.focused)) {
|
||||
return ${componentColor('md.comp.switch.selected.focus.state-layer')};
|
||||
}
|
||||
return null;
|
||||
}
|
||||
if (states.contains(MaterialState.pressed)) {
|
||||
return ${componentColor('md.comp.switch.unselected.pressed.state-layer')};
|
||||
}
|
||||
if (states.contains(MaterialState.hovered)) {
|
||||
return ${componentColor('md.comp.switch.unselected.hover.state-layer')};
|
||||
}
|
||||
if (states.contains(MaterialState.focused)) {
|
||||
return ${componentColor('md.comp.switch.unselected.focus.state-layer')};
|
||||
}
|
||||
return null;
|
||||
});
|
||||
}
|
||||
|
||||
@override
|
||||
double get splashRadius => ${tokens['md.comp.switch.state-layer.size']} / 2;
|
||||
}
|
||||
|
||||
class _SwitchConfigM3 with _SwitchConfig {
|
||||
_SwitchConfigM3(this.context)
|
||||
: _colors = Theme.of(context).colorScheme;
|
||||
|
||||
BuildContext context;
|
||||
final ColorScheme _colors;
|
||||
|
||||
static const double iconSize = ${tokens['md.comp.switch.unselected.icon.size']};
|
||||
|
||||
@override
|
||||
double get activeThumbRadius => ${tokens['md.comp.switch.selected.handle.width']} / 2;
|
||||
|
||||
@override
|
||||
MaterialStateProperty<Color> get iconColor {
|
||||
return MaterialStateProperty.resolveWith((Set<MaterialState> states) {
|
||||
if (states.contains(MaterialState.disabled)) {
|
||||
if (states.contains(MaterialState.selected)) {
|
||||
return ${componentColor('md.comp.switch.disabled.selected.icon')};
|
||||
}
|
||||
return ${componentColor('md.comp.switch.disabled.unselected.icon')};
|
||||
}
|
||||
if (states.contains(MaterialState.selected)) {
|
||||
if (states.contains(MaterialState.pressed)) {
|
||||
return ${componentColor('md.comp.switch.selected.pressed.icon')};
|
||||
}
|
||||
if (states.contains(MaterialState.hovered)) {
|
||||
return ${componentColor('md.comp.switch.selected.hover.icon')};
|
||||
}
|
||||
if (states.contains(MaterialState.focused)) {
|
||||
return ${componentColor('md.comp.switch.selected.focus.icon')};
|
||||
}
|
||||
return ${componentColor('md.comp.switch.selected.icon')};
|
||||
}
|
||||
if (states.contains(MaterialState.pressed)) {
|
||||
return ${componentColor('md.comp.switch.unselected.pressed.icon')};
|
||||
}
|
||||
if (states.contains(MaterialState.hovered)) {
|
||||
return ${componentColor('md.comp.switch.unselected.hover.icon')};
|
||||
}
|
||||
if (states.contains(MaterialState.focused)) {
|
||||
return ${componentColor('md.comp.switch.unselected.focus.icon')};
|
||||
}
|
||||
return ${componentColor('md.comp.switch.unselected.icon')};
|
||||
});
|
||||
}
|
||||
|
||||
@override
|
||||
double get inactiveThumbRadius => ${tokens['md.comp.switch.unselected.handle.width']} / 2;
|
||||
|
||||
@override
|
||||
double get pressedThumbRadius => ${tokens['md.comp.switch.pressed.handle.width']} / 2;
|
||||
|
||||
@override
|
||||
double get switchHeight => _kSwitchMinSize + 8.0;
|
||||
|
||||
@override
|
||||
double get switchHeightCollapsed => _kSwitchMinSize;
|
||||
|
||||
@override
|
||||
double get switchWidth => trackWidth - 2 * (trackHeight / 2.0) + _kSwitchMinSize;
|
||||
|
||||
@override
|
||||
double get thumbRadiusWithIcon => ${tokens['md.comp.switch.with-icon.handle.width']} / 2;
|
||||
|
||||
@override
|
||||
List<BoxShadow>? get thumbShadow => kElevationToShadow[0];
|
||||
|
||||
@override
|
||||
double get trackHeight => ${tokens['md.comp.switch.track.height']};
|
||||
|
||||
@override
|
||||
MaterialStateProperty<Color?> get trackOutlineColor {
|
||||
return MaterialStateProperty.resolveWith((Set<MaterialState> states) {
|
||||
if (states.contains(MaterialState.selected)) {
|
||||
return null;
|
||||
}
|
||||
if (states.contains(MaterialState.disabled)) {
|
||||
return ${componentColor('md.comp.switch.disabled.unselected.track.outline')}.withOpacity(${opacity('md.comp.switch.disabled.track.opacity')});
|
||||
}
|
||||
return ${componentColor('md.comp.switch.unselected.track.outline')};
|
||||
});
|
||||
}
|
||||
|
||||
@override
|
||||
double get trackWidth => ${tokens['md.comp.switch.track.width']};
|
||||
}
|
||||
''';
|
||||
|
||||
}
|
74
examples/api/lib/material/switch/switch.2.dart
Normal file
74
examples/api/lib/material/switch/switch.2.dart
Normal file
@ -0,0 +1,74 @@
|
||||
// Copyright 2014 The Flutter Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
// Flutter code sample for Switch
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
void main() => runApp(const SwitchApp());
|
||||
|
||||
class SwitchApp extends StatelessWidget {
|
||||
const SwitchApp({super.key});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return MaterialApp(
|
||||
theme: ThemeData(useMaterial3: true, colorSchemeSeed: const Color(0xff6750a4)),
|
||||
home: Scaffold(
|
||||
appBar: AppBar(title: const Text('Switch Sample')),
|
||||
body: const Center(
|
||||
child: SwitchExample(),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class SwitchExample extends StatefulWidget {
|
||||
const SwitchExample({super.key});
|
||||
|
||||
@override
|
||||
State<SwitchExample> createState() => _SwitchExampleState();
|
||||
}
|
||||
|
||||
class _SwitchExampleState extends State<SwitchExample> {
|
||||
bool light0 = true;
|
||||
bool light1 = true;
|
||||
bool light2 = true;
|
||||
|
||||
final MaterialStateProperty<Icon?> thumbIcon = MaterialStateProperty.resolveWith<Icon?>((Set<MaterialState> states) {
|
||||
// Thumb icon when the switch is selected.
|
||||
if (states.contains(MaterialState.selected)) {
|
||||
return const Icon(Icons.check);
|
||||
}
|
||||
return const Icon(Icons.close);
|
||||
},
|
||||
);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: <Widget>[
|
||||
Switch(
|
||||
value: light0,
|
||||
onChanged: (bool value) {
|
||||
setState(() {
|
||||
light0 = value;
|
||||
});
|
||||
},
|
||||
),
|
||||
Switch(
|
||||
thumbIcon: thumbIcon,
|
||||
value: light1,
|
||||
onChanged: (bool value) {
|
||||
setState(() {
|
||||
light1 = value;
|
||||
});
|
||||
},
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
File diff suppressed because it is too large
Load Diff
@ -43,6 +43,7 @@ class SwitchThemeData with Diagnosticable {
|
||||
this.mouseCursor,
|
||||
this.overlayColor,
|
||||
this.splashRadius,
|
||||
this.thumbIcon,
|
||||
});
|
||||
|
||||
/// {@macro flutter.material.switch.thumbColor}
|
||||
@ -76,6 +77,11 @@ class SwitchThemeData with Diagnosticable {
|
||||
/// If specified, overrides the default value of [Switch.splashRadius].
|
||||
final double? splashRadius;
|
||||
|
||||
/// {@macro flutter.material.switch.thumbIcon}
|
||||
///
|
||||
/// It is overridden by [Switch.thumbIcon].
|
||||
final MaterialStateProperty<Icon?>? thumbIcon;
|
||||
|
||||
/// Creates a copy of this object but with the given fields replaced with the
|
||||
/// new values.
|
||||
SwitchThemeData copyWith({
|
||||
@ -85,6 +91,7 @@ class SwitchThemeData with Diagnosticable {
|
||||
MaterialStateProperty<MouseCursor?>? mouseCursor,
|
||||
MaterialStateProperty<Color?>? overlayColor,
|
||||
double? splashRadius,
|
||||
MaterialStateProperty<Icon?>? thumbIcon,
|
||||
}) {
|
||||
return SwitchThemeData(
|
||||
thumbColor: thumbColor ?? this.thumbColor,
|
||||
@ -93,6 +100,7 @@ class SwitchThemeData with Diagnosticable {
|
||||
mouseCursor: mouseCursor ?? this.mouseCursor,
|
||||
overlayColor: overlayColor ?? this.overlayColor,
|
||||
splashRadius: splashRadius ?? this.splashRadius,
|
||||
thumbIcon: thumbIcon ?? this.thumbIcon,
|
||||
);
|
||||
}
|
||||
|
||||
@ -107,6 +115,7 @@ class SwitchThemeData with Diagnosticable {
|
||||
mouseCursor: t < 0.5 ? a?.mouseCursor : b?.mouseCursor,
|
||||
overlayColor: MaterialStateProperty.lerp<Color?>(a?.overlayColor, b?.overlayColor, t, Color.lerp),
|
||||
splashRadius: lerpDouble(a?.splashRadius, b?.splashRadius, t),
|
||||
thumbIcon: t < 0.5 ? a?.thumbIcon : b?.thumbIcon,
|
||||
);
|
||||
}
|
||||
|
||||
@ -118,6 +127,7 @@ class SwitchThemeData with Diagnosticable {
|
||||
mouseCursor,
|
||||
overlayColor,
|
||||
splashRadius,
|
||||
thumbIcon,
|
||||
);
|
||||
|
||||
@override
|
||||
@ -134,7 +144,8 @@ class SwitchThemeData with Diagnosticable {
|
||||
&& other.materialTapTargetSize == materialTapTargetSize
|
||||
&& other.mouseCursor == mouseCursor
|
||||
&& other.overlayColor == overlayColor
|
||||
&& other.splashRadius == splashRadius;
|
||||
&& other.splashRadius == splashRadius
|
||||
&& other.thumbIcon == thumbIcon;
|
||||
}
|
||||
|
||||
@override
|
||||
@ -146,6 +157,7 @@ class SwitchThemeData with Diagnosticable {
|
||||
properties.add(DiagnosticsProperty<MaterialStateProperty<MouseCursor?>>('mouseCursor', mouseCursor, defaultValue: null));
|
||||
properties.add(DiagnosticsProperty<MaterialStateProperty<Color?>>('overlayColor', overlayColor, defaultValue: null));
|
||||
properties.add(DoubleProperty('splashRadius', splashRadius, defaultValue: null));
|
||||
properties.add(DiagnosticsProperty<MaterialStateProperty<Icon?>>('thumbIcon', thumbIcon, defaultValue: null));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1252,7 +1252,7 @@ class ThemeData with Diagnosticable {
|
||||
/// * Typography: `typography` (see table above)
|
||||
///
|
||||
/// ### Components
|
||||
/// * Common buttons: [ElevatedButton], [FilledButton], [OutlinedButton], [TextButton]
|
||||
/// * Common buttons: [ElevatedButton], [FilledButton], [OutlinedButton], [TextButton], [IconButton]
|
||||
/// * FAB: [FloatingActionButton]
|
||||
/// * Extended FAB: [FloatingActionButton.extended]
|
||||
/// * Cards: [Card]
|
||||
@ -1266,6 +1266,7 @@ class ThemeData with Diagnosticable {
|
||||
/// * Lists: [ListTile]
|
||||
/// * Navigation bar: [NavigationBar] (new, replacing [BottomNavigationBar])
|
||||
/// * [Navigation rail](https://m3.material.io/components/navigation-rail): [NavigationRail]
|
||||
/// * Switch: [Switch]
|
||||
/// * Top app bar: [AppBar]
|
||||
///
|
||||
/// In addition, this flag enables features introduced in Android 12.
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -23,6 +23,7 @@ void main() {
|
||||
expect(themeData.materialTapTargetSize, null);
|
||||
expect(themeData.overlayColor, null);
|
||||
expect(themeData.splashRadius, null);
|
||||
expect(themeData.thumbIcon, null);
|
||||
|
||||
const SwitchTheme theme = SwitchTheme(data: SwitchThemeData(), child: SizedBox());
|
||||
expect(theme.data.thumbColor, null);
|
||||
@ -31,6 +32,7 @@ void main() {
|
||||
expect(theme.data.materialTapTargetSize, null);
|
||||
expect(theme.data.overlayColor, null);
|
||||
expect(theme.data.splashRadius, null);
|
||||
expect(theme.data.thumbIcon, null);
|
||||
});
|
||||
|
||||
testWidgets('Default SwitchThemeData debugFillProperties', (WidgetTester tester) async {
|
||||
@ -54,6 +56,7 @@ void main() {
|
||||
materialTapTargetSize: MaterialTapTargetSize.shrinkWrap,
|
||||
overlayColor: MaterialStatePropertyAll<Color>(Color(0xfffffff2)),
|
||||
splashRadius: 1.0,
|
||||
thumbIcon: MaterialStatePropertyAll<Icon>(Icon(IconData(123))),
|
||||
).debugFillProperties(builder);
|
||||
|
||||
final List<String> description = builder.properties
|
||||
@ -67,6 +70,7 @@ void main() {
|
||||
expect(description[3], 'mouseCursor: MaterialStatePropertyAll(SystemMouseCursor(click))');
|
||||
expect(description[4], 'overlayColor: MaterialStatePropertyAll(Color(0xfffffff2))');
|
||||
expect(description[5], 'splashRadius: 1.0');
|
||||
expect(description[6], 'thumbIcon: MaterialStatePropertyAll(Icon(IconData(U+0007B)))');
|
||||
});
|
||||
|
||||
testWidgets('Switch is themeable', (WidgetTester tester) async {
|
||||
@ -81,37 +85,48 @@ void main() {
|
||||
const Color focusOverlayColor = Color(0xfffffff4);
|
||||
const Color hoverOverlayColor = Color(0xfffffff5);
|
||||
const double splashRadius = 1.0;
|
||||
const Icon icon1 = Icon(Icons.check);
|
||||
const Icon icon2 = Icon(Icons.close);
|
||||
|
||||
final ThemeData themeData = ThemeData(
|
||||
useMaterial3: true,
|
||||
switchTheme: SwitchThemeData(
|
||||
thumbColor: MaterialStateProperty.resolveWith((Set<MaterialState> states) {
|
||||
if (states.contains(MaterialState.selected)) {
|
||||
return selectedThumbColor;
|
||||
}
|
||||
return defaultThumbColor;
|
||||
}),
|
||||
trackColor: MaterialStateProperty.resolveWith((Set<MaterialState> states) {
|
||||
if (states.contains(MaterialState.selected)) {
|
||||
return selectedTrackColor;
|
||||
}
|
||||
return defaultTrackColor;
|
||||
}),
|
||||
mouseCursor: const MaterialStatePropertyAll<MouseCursor>(mouseCursor),
|
||||
materialTapTargetSize: materialTapTargetSize,
|
||||
overlayColor: MaterialStateProperty.resolveWith((Set<MaterialState> states) {
|
||||
if (states.contains(MaterialState.focused)) {
|
||||
return focusOverlayColor;
|
||||
}
|
||||
if (states.contains(MaterialState.hovered)) {
|
||||
return hoverOverlayColor;
|
||||
}
|
||||
return null;
|
||||
}),
|
||||
splashRadius: splashRadius,
|
||||
thumbIcon: MaterialStateProperty.resolveWith((Set<MaterialState> states) {
|
||||
if (states.contains(MaterialState.selected)) {
|
||||
return icon1;
|
||||
}
|
||||
return icon2;
|
||||
}),
|
||||
),
|
||||
);
|
||||
final bool material3 = themeData.useMaterial3;
|
||||
Widget buildSwitch({bool selected = false, bool autofocus = false}) {
|
||||
return MaterialApp(
|
||||
theme: ThemeData(
|
||||
switchTheme: SwitchThemeData(
|
||||
thumbColor: MaterialStateProperty.resolveWith((Set<MaterialState> states) {
|
||||
if (states.contains(MaterialState.selected)) {
|
||||
return selectedThumbColor;
|
||||
}
|
||||
return defaultThumbColor;
|
||||
}),
|
||||
trackColor: MaterialStateProperty.resolveWith((Set<MaterialState> states) {
|
||||
if (states.contains(MaterialState.selected)) {
|
||||
return selectedTrackColor;
|
||||
}
|
||||
return defaultTrackColor;
|
||||
}),
|
||||
mouseCursor: const MaterialStatePropertyAll<MouseCursor>(mouseCursor),
|
||||
materialTapTargetSize: materialTapTargetSize,
|
||||
overlayColor: MaterialStateProperty.resolveWith((Set<MaterialState> states) {
|
||||
if (states.contains(MaterialState.focused)) {
|
||||
return focusOverlayColor;
|
||||
}
|
||||
if (states.contains(MaterialState.hovered)) {
|
||||
return hoverOverlayColor;
|
||||
}
|
||||
return null;
|
||||
}),
|
||||
splashRadius: splashRadius,
|
||||
),
|
||||
),
|
||||
theme: themeData,
|
||||
home: Scaffold(
|
||||
body: Switch(
|
||||
dragStartBehavior: DragStartBehavior.down,
|
||||
@ -128,27 +143,39 @@ void main() {
|
||||
await tester.pumpAndSettle();
|
||||
expect(
|
||||
_getSwitchMaterial(tester),
|
||||
paints
|
||||
material3
|
||||
? (paints
|
||||
..rrect(color: defaultTrackColor)
|
||||
..rrect(color: themeData.colorScheme.outline)
|
||||
..circle(color: defaultThumbColor)
|
||||
..paragraph()
|
||||
)
|
||||
: (paints
|
||||
..rrect(color: defaultTrackColor)
|
||||
..circle()
|
||||
..circle()
|
||||
..circle()
|
||||
..circle(color: defaultThumbColor),
|
||||
..circle(color: defaultThumbColor)
|
||||
)
|
||||
);
|
||||
// Size from MaterialTapTargetSize.shrinkWrap.
|
||||
expect(tester.getSize(find.byType(Switch)), const Size(59.0, 40.0));
|
||||
expect(tester.getSize(find.byType(Switch)), material3 ? const Size(60.0, 40.0) : const Size(59.0, 40.0));
|
||||
|
||||
// Selected switch.
|
||||
await tester.pumpWidget(buildSwitch(selected: true));
|
||||
await tester.pumpAndSettle();
|
||||
expect(
|
||||
_getSwitchMaterial(tester),
|
||||
paints
|
||||
material3
|
||||
? (paints
|
||||
..rrect(color: selectedTrackColor)
|
||||
..circle(color: selectedThumbColor)..paragraph())
|
||||
: (paints
|
||||
..rrect(color: selectedTrackColor)
|
||||
..circle()
|
||||
..circle()
|
||||
..circle()
|
||||
..circle(color: selectedThumbColor),
|
||||
..circle(color: selectedThumbColor))
|
||||
);
|
||||
|
||||
// Switch with hover.
|
||||
@ -187,36 +214,45 @@ void main() {
|
||||
const Color hoverColor = Color(0xffffff5f);
|
||||
const double splashRadius = 2.0;
|
||||
|
||||
final ThemeData themeData = ThemeData(
|
||||
switchTheme: SwitchThemeData(
|
||||
thumbColor: MaterialStateProperty.resolveWith((Set<MaterialState> states) {
|
||||
if (states.contains(MaterialState.selected)) {
|
||||
return themeSelectedThumbColor;
|
||||
}
|
||||
return themeDefaultThumbColor;
|
||||
}),
|
||||
trackColor: MaterialStateProperty.resolveWith((Set<MaterialState> states) {
|
||||
if (states.contains(MaterialState.selected)) {
|
||||
return themeSelectedTrackColor;
|
||||
}
|
||||
return themeDefaultTrackColor;
|
||||
}),
|
||||
mouseCursor: const MaterialStatePropertyAll<MouseCursor>(themeMouseCursor),
|
||||
materialTapTargetSize: themeMaterialTapTargetSize,
|
||||
overlayColor: MaterialStateProperty.resolveWith((Set<MaterialState> states) {
|
||||
if (states.contains(MaterialState.focused)) {
|
||||
return themeFocusOverlayColor;
|
||||
}
|
||||
if (states.contains(MaterialState.hovered)) {
|
||||
return themeHoverOverlayColor;
|
||||
}
|
||||
return null;
|
||||
}),
|
||||
splashRadius: themeSplashRadius,
|
||||
thumbIcon: MaterialStateProperty.resolveWith((Set<MaterialState> states) {
|
||||
if (states.contains(MaterialState.selected)) {
|
||||
return null;
|
||||
}
|
||||
return null;
|
||||
}),
|
||||
),
|
||||
);
|
||||
final bool material3 = themeData.useMaterial3;
|
||||
|
||||
Widget buildSwitch({bool selected = false, bool autofocus = false}) {
|
||||
return MaterialApp(
|
||||
theme: ThemeData(
|
||||
switchTheme: SwitchThemeData(
|
||||
thumbColor: MaterialStateProperty.resolveWith((Set<MaterialState> states) {
|
||||
if (states.contains(MaterialState.selected)) {
|
||||
return themeSelectedThumbColor;
|
||||
}
|
||||
return themeDefaultThumbColor;
|
||||
}),
|
||||
trackColor: MaterialStateProperty.resolveWith((Set<MaterialState> states) {
|
||||
if (states.contains(MaterialState.selected)) {
|
||||
return themeSelectedTrackColor;
|
||||
}
|
||||
return themeDefaultTrackColor;
|
||||
}),
|
||||
mouseCursor: const MaterialStatePropertyAll<MouseCursor>(themeMouseCursor),
|
||||
materialTapTargetSize: themeMaterialTapTargetSize,
|
||||
overlayColor: MaterialStateProperty.resolveWith((Set<MaterialState> states) {
|
||||
if (states.contains(MaterialState.focused)) {
|
||||
return themeFocusOverlayColor;
|
||||
}
|
||||
if (states.contains(MaterialState.hovered)) {
|
||||
return themeHoverOverlayColor;
|
||||
}
|
||||
return null;
|
||||
}),
|
||||
splashRadius: themeSplashRadius,
|
||||
),
|
||||
),
|
||||
theme: themeData,
|
||||
home: Scaffold(
|
||||
body: Switch(
|
||||
value: selected,
|
||||
@ -239,6 +275,12 @@ void main() {
|
||||
focusColor: focusColor,
|
||||
hoverColor: hoverColor,
|
||||
splashRadius: splashRadius,
|
||||
thumbIcon: MaterialStateProperty.resolveWith((Set<MaterialState> states) {
|
||||
if (states.contains(MaterialState.selected)) {
|
||||
return const Icon(Icons.add);
|
||||
}
|
||||
return const Icon(Icons.access_alarm);
|
||||
}),
|
||||
),
|
||||
),
|
||||
);
|
||||
@ -249,27 +291,36 @@ void main() {
|
||||
await tester.pumpAndSettle();
|
||||
expect(
|
||||
_getSwitchMaterial(tester),
|
||||
paints
|
||||
material3
|
||||
? (paints
|
||||
..rrect(color: defaultTrackColor)
|
||||
..rrect(color: themeData.colorScheme.outline)
|
||||
..circle(color: defaultThumbColor)..paragraph(offset: const Offset(12, 16)))
|
||||
: (paints
|
||||
..rrect(color: defaultTrackColor)
|
||||
..circle()
|
||||
..circle()
|
||||
..circle()
|
||||
..circle(color: defaultThumbColor),
|
||||
..circle(color: defaultThumbColor))
|
||||
);
|
||||
// Size from MaterialTapTargetSize.shrinkWrap.
|
||||
expect(tester.getSize(find.byType(Switch)), const Size(59.0, 40.0));
|
||||
expect(tester.getSize(find.byType(Switch)), material3 ? const Size(60.0, 40.0) : const Size(59.0, 40.0));
|
||||
|
||||
// Selected switch.
|
||||
await tester.pumpWidget(buildSwitch(selected: true));
|
||||
await tester.pumpAndSettle();
|
||||
expect(
|
||||
_getSwitchMaterial(tester),
|
||||
paints
|
||||
material3
|
||||
? (paints
|
||||
..rrect(color: selectedTrackColor)
|
||||
..circle(color: selectedThumbColor))
|
||||
: (paints
|
||||
..rrect(color: selectedTrackColor)
|
||||
..circle()
|
||||
..circle()
|
||||
..circle()
|
||||
..circle(color: selectedThumbColor),
|
||||
..circle(color: selectedThumbColor))
|
||||
);
|
||||
|
||||
// Switch with hover.
|
||||
@ -298,24 +349,27 @@ void main() {
|
||||
const Color defaultTrackColor = Color(0xffffff2f);
|
||||
const Color selectedTrackColor = Color(0xffffff3f);
|
||||
|
||||
final ThemeData themeData = ThemeData(
|
||||
switchTheme: SwitchThemeData(
|
||||
thumbColor: MaterialStateProperty.resolveWith((Set<MaterialState> states) {
|
||||
if (states.contains(MaterialState.selected)) {
|
||||
return themeSelectedThumbColor;
|
||||
}
|
||||
return themeDefaultThumbColor;
|
||||
}),
|
||||
trackColor: MaterialStateProperty.resolveWith((Set<MaterialState> states) {
|
||||
if (states.contains(MaterialState.selected)) {
|
||||
return themeSelectedTrackColor;
|
||||
}
|
||||
return themeDefaultTrackColor;
|
||||
}),
|
||||
),
|
||||
);
|
||||
final bool material3 = themeData.useMaterial3;
|
||||
|
||||
Widget buildSwitch({bool selected = false, bool autofocus = false}) {
|
||||
return MaterialApp(
|
||||
theme: ThemeData(
|
||||
switchTheme: SwitchThemeData(
|
||||
thumbColor: MaterialStateProperty.resolveWith((Set<MaterialState> states) {
|
||||
if (states.contains(MaterialState.selected)) {
|
||||
return themeSelectedThumbColor;
|
||||
}
|
||||
return themeDefaultThumbColor;
|
||||
}),
|
||||
trackColor: MaterialStateProperty.resolveWith((Set<MaterialState> states) {
|
||||
if (states.contains(MaterialState.selected)) {
|
||||
return themeSelectedTrackColor;
|
||||
}
|
||||
return themeDefaultTrackColor;
|
||||
}),
|
||||
),
|
||||
),
|
||||
theme: themeData,
|
||||
home: Scaffold(
|
||||
body: Switch(
|
||||
value: selected,
|
||||
@ -335,12 +389,17 @@ void main() {
|
||||
await tester.pumpAndSettle();
|
||||
expect(
|
||||
_getSwitchMaterial(tester),
|
||||
paints
|
||||
..rrect(color: defaultTrackColor)
|
||||
..circle()
|
||||
..circle()
|
||||
..circle()
|
||||
..circle(color: defaultThumbColor),
|
||||
material3
|
||||
? (paints
|
||||
..rrect(color: defaultTrackColor)
|
||||
..rrect(color: themeData.colorScheme.outline)
|
||||
..circle(color: defaultThumbColor))
|
||||
: (paints
|
||||
..rrect(color: defaultTrackColor)
|
||||
..circle()
|
||||
..circle()
|
||||
..circle()
|
||||
..circle(color: defaultThumbColor))
|
||||
);
|
||||
|
||||
// Selected switch.
|
||||
@ -348,12 +407,16 @@ void main() {
|
||||
await tester.pumpAndSettle();
|
||||
expect(
|
||||
_getSwitchMaterial(tester),
|
||||
paints
|
||||
material3
|
||||
? (paints
|
||||
..rrect(color: selectedTrackColor)
|
||||
..circle(color: selectedThumbColor))
|
||||
: (paints
|
||||
..rrect(color: selectedTrackColor)
|
||||
..circle()
|
||||
..circle()
|
||||
..circle()
|
||||
..circle(color: selectedThumbColor),
|
||||
..circle(color: selectedThumbColor))
|
||||
);
|
||||
});
|
||||
|
||||
@ -371,15 +434,17 @@ void main() {
|
||||
return null;
|
||||
}
|
||||
const double splashRadius = 24.0;
|
||||
final ThemeData themeData = ThemeData(
|
||||
switchTheme: SwitchThemeData(
|
||||
overlayColor: MaterialStateProperty.resolveWith(getOverlayColor),
|
||||
splashRadius: splashRadius,
|
||||
),
|
||||
);
|
||||
final bool material3 = themeData.useMaterial3;
|
||||
|
||||
Widget buildSwitch({required bool active}) {
|
||||
return MaterialApp(
|
||||
theme: ThemeData(
|
||||
switchTheme: SwitchThemeData(
|
||||
overlayColor: MaterialStateProperty.resolveWith(getOverlayColor),
|
||||
splashRadius: splashRadius,
|
||||
),
|
||||
),
|
||||
theme: themeData,
|
||||
home: Scaffold(
|
||||
body: Switch(
|
||||
value: active,
|
||||
@ -395,12 +460,20 @@ void main() {
|
||||
|
||||
expect(
|
||||
_getSwitchMaterial(tester),
|
||||
paints
|
||||
material3
|
||||
? ((paints
|
||||
..rrect()
|
||||
..rrect())
|
||||
..circle(
|
||||
color: inactivePressedOverlayColor,
|
||||
radius: splashRadius,
|
||||
))
|
||||
: (paints
|
||||
..rrect()
|
||||
..circle(
|
||||
color: inactivePressedOverlayColor,
|
||||
radius: splashRadius,
|
||||
),
|
||||
)),
|
||||
reason: 'Inactive pressed Switch should have overlay color: $inactivePressedOverlayColor',
|
||||
);
|
||||
|
||||
@ -426,14 +499,16 @@ void main() {
|
||||
const Color localThemeThumbColor = Color(0xffff0000);
|
||||
const Color localThemeTrackColor = Color(0xffff0000);
|
||||
|
||||
final ThemeData themeData = ThemeData(
|
||||
switchTheme: const SwitchThemeData(
|
||||
thumbColor: MaterialStatePropertyAll<Color>(globalThemeThumbColor),
|
||||
trackColor: MaterialStatePropertyAll<Color>(globalThemeTrackColor),
|
||||
),
|
||||
);
|
||||
final bool material3 = themeData.useMaterial3;
|
||||
Widget buildSwitch({bool selected = false, bool autofocus = false}) {
|
||||
return MaterialApp(
|
||||
theme: ThemeData(
|
||||
switchTheme: const SwitchThemeData(
|
||||
thumbColor: MaterialStatePropertyAll<Color>(globalThemeThumbColor),
|
||||
trackColor: MaterialStatePropertyAll<Color>(globalThemeTrackColor),
|
||||
),
|
||||
),
|
||||
theme: themeData,
|
||||
home: Scaffold(
|
||||
body: SwitchTheme(
|
||||
data: const SwitchThemeData(
|
||||
@ -454,12 +529,16 @@ void main() {
|
||||
await tester.pumpAndSettle();
|
||||
expect(
|
||||
_getSwitchMaterial(tester),
|
||||
paints
|
||||
material3
|
||||
? (paints
|
||||
..rrect(color: localThemeTrackColor)
|
||||
..circle(color: localThemeThumbColor))
|
||||
: (paints
|
||||
..rrect(color: localThemeTrackColor)
|
||||
..circle()
|
||||
..circle()
|
||||
..circle()
|
||||
..circle(color: localThemeThumbColor),
|
||||
..circle(color: localThemeThumbColor))
|
||||
);
|
||||
});
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user