Skip to content

Commit 97d0247

Browse files
authored
Add Material 3 support for Slider - Part 1 (#114079)
1 parent f10021b commit 97d0247

File tree

5 files changed

+854
-57
lines changed

5 files changed

+854
-57
lines changed

dev/tools/gen_defaults/bin/gen_defaults.dart

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ import 'package:gen_defaults/navigation_rail_template.dart';
3838
import 'package:gen_defaults/popup_menu_template.dart';
3939
import 'package:gen_defaults/progress_indicator_template.dart';
4040
import 'package:gen_defaults/radio_template.dart';
41+
import 'package:gen_defaults/slider_template.dart';
4142
import 'package:gen_defaults/surface_tint.dart';
4243
import 'package:gen_defaults/switch_template.dart';
4344
import 'package:gen_defaults/text_field_template.dart';
@@ -144,6 +145,7 @@ Future<void> main(List<String> args) async {
144145
PopupMenuTemplate('PopupMenu', '$materialLib/popup_menu.dart', tokens).updateFile();
145146
ProgressIndicatorTemplate('ProgressIndicator', '$materialLib/progress_indicator.dart', tokens).updateFile();
146147
RadioTemplate('Radio<T>', '$materialLib/radio.dart', tokens).updateFile();
148+
SliderTemplate('md.comp.slider', 'Slider', '$materialLib/slider.dart', tokens).updateFile();
147149
SurfaceTintTemplate('SurfaceTint', '$materialLib/elevation_overlay.dart', tokens).updateFile();
148150
SwitchTemplate('Switch', '$materialLib/switch.dart', tokens).updateFile();
149151
TextFieldTemplate('TextField', '$materialLib/text_field.dart', tokens).updateFile();
Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
// Copyright 2014 The Flutter Authors. All rights reserved.
2+
// Use of this source code is governed by a BSD-style license that can be
3+
// found in the LICENSE file.
4+
5+
import 'template.dart';
6+
7+
class SliderTemplate extends TokenTemplate {
8+
const SliderTemplate(this.tokenGroup, super.blockName, super.fileName, super.tokens, {
9+
super.colorSchemePrefix = '_colors.',
10+
});
11+
12+
final String tokenGroup;
13+
14+
@override
15+
String generate() => '''
16+
class _${blockName}DefaultsM3 extends SliderThemeData {
17+
_${blockName}DefaultsM3(this.context)
18+
: _colors = Theme.of(context).colorScheme,
19+
super(trackHeight: ${tokens['$tokenGroup.active.track.height']});
20+
21+
final BuildContext context;
22+
final ColorScheme _colors;
23+
24+
@override
25+
Color? get activeTrackColor => ${componentColor('$tokenGroup.active.track')};
26+
27+
@override
28+
Color? get inactiveTrackColor => ${componentColor('$tokenGroup.inactive.track')};
29+
30+
@override
31+
Color? get secondaryActiveTrackColor => _colors.primary.withOpacity(0.54);
32+
33+
@override
34+
Color? get disabledActiveTrackColor => ${componentColor('$tokenGroup.disabled.active.track')};
35+
36+
@override
37+
Color? get disabledInactiveTrackColor => ${componentColor('$tokenGroup.disabled.inactive.track')};
38+
39+
@override
40+
Color? get disabledSecondaryActiveTrackColor => _colors.onSurface.withOpacity(0.12);
41+
42+
@override
43+
Color? get activeTickMarkColor => ${componentColor('$tokenGroup.with-tick-marks.active.container')};
44+
45+
@override
46+
Color? get inactiveTickMarkColor => ${componentColor('$tokenGroup.with-tick-marks.inactive.container')};
47+
48+
@override
49+
Color? get disabledActiveTickMarkColor => ${componentColor('$tokenGroup.with-tick-marks.disabled.container')};
50+
51+
@override
52+
Color? get disabledInactiveTickMarkColor => ${componentColor('$tokenGroup.with-tick-marks.disabled.container')};
53+
54+
@override
55+
Color? get thumbColor => ${componentColor('$tokenGroup.handle')};
56+
57+
@override
58+
Color? get disabledThumbColor => Color.alphaBlend(${componentColor('$tokenGroup.disabled.handle')}, _colors.surface);
59+
60+
@override
61+
Color? get overlayColor => MaterialStateColor.resolveWith((Set<MaterialState> states) {
62+
if (states.contains(MaterialState.hovered)) {
63+
return ${componentColor('$tokenGroup.hover.state-layer')};
64+
}
65+
if (states.contains(MaterialState.focused)) {
66+
return ${componentColor('$tokenGroup.focus.state-layer')};
67+
}
68+
if (states.contains(MaterialState.dragged)) {
69+
return ${componentColor('$tokenGroup.pressed.state-layer')};
70+
}
71+
72+
return Colors.transparent;
73+
});
74+
}
75+
''';
76+
77+
}

packages/flutter/lib/src/material/slider.dart

Lines changed: 159 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@ import 'package:flutter/rendering.dart';
1212
import 'package:flutter/scheduler.dart' show timeDilation;
1313
import 'package:flutter/services.dart';
1414

15+
import 'color_scheme.dart';
16+
import 'colors.dart';
1517
import 'constants.dart';
1618
import 'debug.dart';
1719
import 'material.dart';
@@ -374,8 +376,9 @@ class Slider extends StatefulWidget {
374376
/// The "active" side of the slider is the side between the thumb and the
375377
/// minimum value.
376378
///
377-
/// Defaults to [SliderThemeData.activeTrackColor] of the current
378-
/// [SliderTheme].
379+
/// If null, [SliderThemeData.activeTrackColor] of the ambient
380+
/// [SliderTheme] is used. If that is null, [ColorScheme.primary] of the
381+
/// surrounding [ThemeData] is used.
379382
///
380383
/// Using a [SliderTheme] gives much more fine-grained control over the
381384
/// appearance of various components of the slider.
@@ -386,8 +389,10 @@ class Slider extends StatefulWidget {
386389
/// The "inactive" side of the slider is the side between the thumb and the
387390
/// maximum value.
388391
///
389-
/// Defaults to the [SliderThemeData.inactiveTrackColor] of the current
390-
/// [SliderTheme].
392+
/// If null, [SliderThemeData.inactiveTrackColor] of the ambient [SliderTheme]
393+
/// is used. If that is null and [ThemeData.useMaterial3] is true,
394+
/// [ColorScheme.surfaceVariant] will be used, otherwise [ColorScheme.primary]
395+
/// with an opacity of 0.24 will be used.
391396
///
392397
/// Using a [SliderTheme] gives much more fine-grained control over the
393398
/// appearance of various components of the slider.
@@ -401,6 +406,9 @@ class Slider extends StatefulWidget {
401406
/// Defaults to the [SliderThemeData.secondaryActiveTrackColor] of the current
402407
/// [SliderTheme].
403408
///
409+
/// If that is also null, defaults to [ColorScheme.primary] with an
410+
/// opacity of 0.54.
411+
///
404412
/// Using a [SliderTheme] gives much more fine-grained control over the
405413
/// appearance of various components of the slider.
406414
///
@@ -409,19 +417,27 @@ class Slider extends StatefulWidget {
409417

410418
/// The color of the thumb.
411419
///
412-
/// If this color is null:
413-
/// * [Slider] will use [activeColor].
420+
/// If this color is null, [Slider] will use [activeColor], If [activeColor]
421+
/// is also null, [Slider] will use [SliderThemeData.thumbColor].
422+
///
423+
/// If that is also null, defaults to [ColorScheme.primary].
424+
///
414425
/// * [CupertinoSlider] will have a white thumb
415426
/// (like the native default iOS slider).
416427
final Color? thumbColor;
417428

418429
/// The highlight color that's typically used to indicate that
419-
/// the slider is focused, hovered, or dragged.
430+
/// the slider thumb is focused, hovered, or dragged.
420431
///
421432
/// If this property is null, [Slider] will use [activeColor] with
422433
/// with an opacity of 0.12, If null, [SliderThemeData.overlayColor]
423-
/// will be used, If this is also null, defaults to [ColorScheme.primary]
424-
/// with an opacity of 0.12.
434+
/// will be used.
435+
///
436+
/// If that is also null, If [ThemeData.useMaterial3] is true,
437+
/// Slider will use [ColorScheme.primary] with an opacity of 0.08 when
438+
/// slider thumb is hovered and with an opacity of 0.12 when slider thumb
439+
/// is focused or dragged, If [ThemeData.useMaterial3] is false, defaults
440+
/// to [ColorScheme.primary] with an opacity of 0.12.
425441
final MaterialStateProperty<Color?>? overlayColor;
426442

427443
/// {@template flutter.material.slider.mouseCursor}
@@ -730,6 +746,7 @@ class _SliderState extends State<Slider> with TickerProviderStateMixin {
730746
Widget _buildMaterialSlider(BuildContext context) {
731747
final ThemeData theme = Theme.of(context);
732748
SliderThemeData sliderTheme = SliderTheme.of(context);
749+
final SliderThemeData defaults = theme.useMaterial3 ? _SliderDefaultsM3(context) : _SliderDefaultsM2(context);
733750

734751
// If the widget has active or inactive colors specified, then we plug them
735752
// in to the slider theme as best we can. If the developer wants more
@@ -738,7 +755,6 @@ class _SliderState extends State<Slider> with TickerProviderStateMixin {
738755
// the default shapes and text styles are aligned to the Material
739756
// Guidelines.
740757

741-
const double defaultTrackHeight = 4;
742758
const SliderTrackShape defaultTrackShape = RoundedRectSliderTrackShape();
743759
const SliderTickMarkShape defaultTickMarkShape = RoundSliderTickMarkShape();
744760
const SliderComponentShape defaultOverlayShape = RoundSliderOverlayShape();
@@ -769,23 +785,23 @@ class _SliderState extends State<Slider> with TickerProviderStateMixin {
769785
return widget.overlayColor?.resolve(states)
770786
?? widget.activeColor?.withOpacity(0.12)
771787
?? MaterialStateProperty.resolveAs<Color?>(sliderTheme.overlayColor, states)
772-
?? theme.colorScheme.primary.withOpacity(0.12);
788+
?? MaterialStateProperty.resolveAs<Color?>(defaults.overlayColor, states);
773789
}
774790

775791
sliderTheme = sliderTheme.copyWith(
776-
trackHeight: sliderTheme.trackHeight ?? defaultTrackHeight,
777-
activeTrackColor: widget.activeColor ?? sliderTheme.activeTrackColor ?? theme.colorScheme.primary,
778-
inactiveTrackColor: widget.inactiveColor ?? sliderTheme.inactiveTrackColor ?? theme.colorScheme.primary.withOpacity(0.24),
779-
secondaryActiveTrackColor: widget.secondaryActiveColor ?? sliderTheme.secondaryActiveTrackColor ?? theme.colorScheme.primary.withOpacity(0.54),
780-
disabledActiveTrackColor: sliderTheme.disabledActiveTrackColor ?? theme.colorScheme.onSurface.withOpacity(0.32),
781-
disabledInactiveTrackColor: sliderTheme.disabledInactiveTrackColor ?? theme.colorScheme.onSurface.withOpacity(0.12),
782-
disabledSecondaryActiveTrackColor: sliderTheme.disabledSecondaryActiveTrackColor ?? theme.colorScheme.onSurface.withOpacity(0.12),
783-
activeTickMarkColor: widget.inactiveColor ?? sliderTheme.activeTickMarkColor ?? theme.colorScheme.onPrimary.withOpacity(0.54),
784-
inactiveTickMarkColor: widget.activeColor ?? sliderTheme.inactiveTickMarkColor ?? theme.colorScheme.primary.withOpacity(0.54),
785-
disabledActiveTickMarkColor: sliderTheme.disabledActiveTickMarkColor ?? theme.colorScheme.onPrimary.withOpacity(0.12),
786-
disabledInactiveTickMarkColor: sliderTheme.disabledInactiveTickMarkColor ?? theme.colorScheme.onSurface.withOpacity(0.12),
787-
thumbColor: widget.thumbColor ?? widget.activeColor ?? sliderTheme.thumbColor ?? theme.colorScheme.primary,
788-
disabledThumbColor: sliderTheme.disabledThumbColor ?? Color.alphaBlend(theme.colorScheme.onSurface.withOpacity(.38), theme.colorScheme.surface),
792+
trackHeight: sliderTheme.trackHeight ?? defaults.trackHeight,
793+
activeTrackColor: widget.activeColor ?? sliderTheme.activeTrackColor ?? defaults.activeTrackColor,
794+
inactiveTrackColor: widget.inactiveColor ?? sliderTheme.inactiveTrackColor ?? defaults.inactiveTrackColor,
795+
secondaryActiveTrackColor: widget.secondaryActiveColor ?? sliderTheme.secondaryActiveTrackColor ?? defaults.secondaryActiveTrackColor,
796+
disabledActiveTrackColor: sliderTheme.disabledActiveTrackColor ?? defaults.disabledActiveTrackColor,
797+
disabledInactiveTrackColor: sliderTheme.disabledInactiveTrackColor ?? defaults.disabledInactiveTrackColor,
798+
disabledSecondaryActiveTrackColor: sliderTheme.disabledSecondaryActiveTrackColor ?? defaults.disabledSecondaryActiveTrackColor,
799+
activeTickMarkColor: widget.inactiveColor ?? sliderTheme.activeTickMarkColor ?? defaults.activeTickMarkColor,
800+
inactiveTickMarkColor: widget.activeColor ?? sliderTheme.inactiveTickMarkColor ?? defaults.inactiveTickMarkColor,
801+
disabledActiveTickMarkColor: sliderTheme.disabledActiveTickMarkColor ?? defaults.disabledActiveTickMarkColor,
802+
disabledInactiveTickMarkColor: sliderTheme.disabledInactiveTickMarkColor ?? defaults.disabledInactiveTickMarkColor,
803+
thumbColor: widget.thumbColor ?? widget.activeColor ?? sliderTheme.thumbColor ?? defaults.thumbColor,
804+
disabledThumbColor: sliderTheme.disabledThumbColor ?? defaults.disabledThumbColor,
789805
overlayColor: effectiveOverlayColor(),
790806
valueIndicatorColor: valueIndicatorColor,
791807
trackShape: sliderTheme.trackShape ?? defaultTrackShape,
@@ -1795,3 +1811,122 @@ class _RenderValueIndicator extends RenderBox with RelayoutWhenSystemFontsChange
17951811
return constraints.smallest;
17961812
}
17971813
}
1814+
1815+
class _SliderDefaultsM2 extends SliderThemeData {
1816+
_SliderDefaultsM2(this.context)
1817+
: _colors = Theme.of(context).colorScheme,
1818+
super(trackHeight: 4.0);
1819+
1820+
final BuildContext context;
1821+
final ColorScheme _colors;
1822+
1823+
@override
1824+
Color? get activeTrackColor => _colors.primary;
1825+
1826+
@override
1827+
Color? get inactiveTrackColor => _colors.primary.withOpacity(0.24);
1828+
1829+
@override
1830+
Color? get secondaryActiveTrackColor => _colors.primary.withOpacity(0.54);
1831+
1832+
@override
1833+
Color? get disabledActiveTrackColor => _colors.onSurface.withOpacity(0.32);
1834+
1835+
@override
1836+
Color? get disabledInactiveTrackColor => _colors.onSurface.withOpacity(0.12);
1837+
1838+
@override
1839+
Color? get disabledSecondaryActiveTrackColor => _colors.onSurface.withOpacity(0.12);
1840+
1841+
@override
1842+
Color? get activeTickMarkColor => _colors.onPrimary.withOpacity(0.54);
1843+
1844+
@override
1845+
Color? get inactiveTickMarkColor => _colors.primary.withOpacity(0.54);
1846+
1847+
@override
1848+
Color? get disabledActiveTickMarkColor => _colors.onPrimary.withOpacity(0.12);
1849+
1850+
@override
1851+
Color? get disabledInactiveTickMarkColor => _colors.onSurface.withOpacity(0.12);
1852+
1853+
@override
1854+
Color? get thumbColor => _colors.primary;
1855+
1856+
@override
1857+
Color? get disabledThumbColor => Color.alphaBlend(_colors.onSurface.withOpacity(.38), _colors.surface);
1858+
1859+
@override
1860+
Color? get overlayColor => _colors.primary.withOpacity(0.12);
1861+
}
1862+
1863+
// BEGIN GENERATED TOKEN PROPERTIES - Slider
1864+
1865+
// Do not edit by hand. The code between the "BEGIN GENERATED" and
1866+
// "END GENERATED" comments are generated from data in the Material
1867+
// Design token database by the script:
1868+
// dev/tools/gen_defaults/bin/gen_defaults.dart.
1869+
1870+
// Token database version: v0_137
1871+
1872+
class _SliderDefaultsM3 extends SliderThemeData {
1873+
_SliderDefaultsM3(this.context)
1874+
: _colors = Theme.of(context).colorScheme,
1875+
super(trackHeight: 4.0);
1876+
1877+
final BuildContext context;
1878+
final ColorScheme _colors;
1879+
1880+
@override
1881+
Color? get activeTrackColor => _colors.primary;
1882+
1883+
@override
1884+
Color? get inactiveTrackColor => _colors.surfaceVariant;
1885+
1886+
@override
1887+
Color? get secondaryActiveTrackColor => _colors.primary.withOpacity(0.54);
1888+
1889+
@override
1890+
Color? get disabledActiveTrackColor => _colors.onSurface.withOpacity(0.38);
1891+
1892+
@override
1893+
Color? get disabledInactiveTrackColor => _colors.onSurface.withOpacity(0.12);
1894+
1895+
@override
1896+
Color? get disabledSecondaryActiveTrackColor => _colors.onSurface.withOpacity(0.12);
1897+
1898+
@override
1899+
Color? get activeTickMarkColor => _colors.onPrimary.withOpacity(0.38);
1900+
1901+
@override
1902+
Color? get inactiveTickMarkColor => _colors.onSurfaceVariant.withOpacity(0.38);
1903+
1904+
@override
1905+
Color? get disabledActiveTickMarkColor => _colors.onSurface.withOpacity(0.38);
1906+
1907+
@override
1908+
Color? get disabledInactiveTickMarkColor => _colors.onSurface.withOpacity(0.38);
1909+
1910+
@override
1911+
Color? get thumbColor => _colors.primary;
1912+
1913+
@override
1914+
Color? get disabledThumbColor => Color.alphaBlend(_colors.onSurface.withOpacity(0.38), _colors.surface);
1915+
1916+
@override
1917+
Color? get overlayColor => MaterialStateColor.resolveWith((Set<MaterialState> states) {
1918+
if (states.contains(MaterialState.hovered)) {
1919+
return _colors.primary.withOpacity(0.08);
1920+
}
1921+
if (states.contains(MaterialState.focused)) {
1922+
return _colors.primary.withOpacity(0.12);
1923+
}
1924+
if (states.contains(MaterialState.dragged)) {
1925+
return _colors.primary.withOpacity(0.12);
1926+
}
1927+
1928+
return Colors.transparent;
1929+
});
1930+
}
1931+
1932+
// END GENERATED TOKEN PROPERTIES - Slider

0 commit comments

Comments
 (0)