mirror of
https://github.com/flutter/flutter.git
synced 2025-06-03 00:51:18 +00:00

Currently, `Switch.factory` delegates to `CupertinoSwitch` when platform is iOS or macOS. This PR is to: * have the factory configure the Material `Switch` for the expected look and feel. * introduce `Adaptation` class to customize themes for the adaptive components.
230 lines
8.5 KiB
Dart
230 lines
8.5 KiB
Dart
// 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(this.context);
|
|
|
|
final BuildContext context;
|
|
late final ColorScheme _colors = Theme.of(context).colorScheme;
|
|
|
|
@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 trackOutlineColor {
|
|
return MaterialStateProperty.resolveWith((Set<MaterialState> states) {
|
|
if (states.contains(MaterialState.selected)) {
|
|
return Colors.transparent;
|
|
}
|
|
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
|
|
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
|
|
MaterialStateProperty<MouseCursor> get mouseCursor {
|
|
return MaterialStateProperty.resolveWith((Set<MaterialState> states)
|
|
=> MaterialStateMouseCursor.clickable.resolve(states));
|
|
}
|
|
|
|
@override
|
|
MaterialStatePropertyAll<double> get trackOutlineWidth => const MaterialStatePropertyAll<double>(${getToken('md.comp.switch.track.outline.width')});
|
|
|
|
@override
|
|
double get splashRadius => ${getToken('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 = ${getToken('md.comp.switch.unselected.icon.size')};
|
|
|
|
@override
|
|
double get activeThumbRadius => ${getToken('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 => ${getToken('md.comp.switch.unselected.handle.width')} / 2;
|
|
|
|
@override
|
|
double get pressedThumbRadius => ${getToken('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 => ${getToken('md.comp.switch.with-icon.handle.width')} / 2;
|
|
|
|
@override
|
|
List<BoxShadow>? get thumbShadow => kElevationToShadow[0];
|
|
|
|
@override
|
|
double get trackHeight => ${getToken('md.comp.switch.track.height')};
|
|
|
|
@override
|
|
double get trackWidth => ${getToken('md.comp.switch.track.width')};
|
|
|
|
// The thumb size at the middle of the track. Hand coded default based on the animation specs.
|
|
@override
|
|
Size get transitionalThumbSize => const Size(34, 22);
|
|
|
|
// Hand coded default based on the animation specs.
|
|
@override
|
|
int get toggleDuration => 300;
|
|
|
|
// Hand coded default based on the animation specs.
|
|
@override
|
|
double? get thumbOffset => null;
|
|
}
|
|
''';
|
|
|
|
}
|