add material slider secondary value (#109808)
This commit is contained in:
parent
1b8fb4c0f2
commit
519a5783c0
66
examples/api/lib/material/slider/slider.1.dart
Normal file
66
examples/api/lib/material/slider/slider.1.dart
Normal file
@ -0,0 +1,66 @@
|
||||
// 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 Slider
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
void main() => runApp(const MyApp());
|
||||
|
||||
class MyApp extends StatelessWidget {
|
||||
const MyApp({super.key});
|
||||
|
||||
static const String _title = 'Flutter Code Sample';
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return MaterialApp(
|
||||
title: _title,
|
||||
home: Scaffold(
|
||||
appBar: AppBar(title: const Text(_title)),
|
||||
body: const MyStatefulWidget(),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class MyStatefulWidget extends StatefulWidget {
|
||||
const MyStatefulWidget({super.key});
|
||||
|
||||
@override
|
||||
State<MyStatefulWidget> createState() => _MyStatefulWidgetState();
|
||||
}
|
||||
|
||||
class _MyStatefulWidgetState extends State<MyStatefulWidget> {
|
||||
double _currentSliderPrimaryValue = 0.2;
|
||||
double _currentSliderSecondaryValue = 0.5;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: <Widget>[
|
||||
Slider(
|
||||
value: _currentSliderPrimaryValue,
|
||||
secondaryTrackValue: _currentSliderSecondaryValue,
|
||||
label: _currentSliderPrimaryValue.round().toString(),
|
||||
onChanged: (double value) {
|
||||
setState(() {
|
||||
_currentSliderPrimaryValue = value;
|
||||
});
|
||||
},
|
||||
),
|
||||
Slider(
|
||||
value: _currentSliderSecondaryValue,
|
||||
label: _currentSliderSecondaryValue.round().toString(),
|
||||
onChanged: (double value) {
|
||||
setState(() {
|
||||
_currentSliderSecondaryValue = value;
|
||||
});
|
||||
},
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
35
examples/api/test/material/slider/slider.1_test.dart
Normal file
35
examples/api/test/material/slider/slider.1_test.dart
Normal file
@ -0,0 +1,35 @@
|
||||
// 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 'package:flutter/material.dart';
|
||||
import 'package:flutter_api_samples/material/slider/slider.1.dart' as example;
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
|
||||
void main() {
|
||||
testWidgets('Slider shows secondary track', (WidgetTester tester) async {
|
||||
await tester.pumpWidget(
|
||||
const example.MyApp(),
|
||||
);
|
||||
|
||||
expect(find.byType(Slider), findsNWidgets(2));
|
||||
|
||||
final Finder slider1Finder = find.byType(Slider).at(0);
|
||||
final Finder slider2Finder = find.byType(Slider).at(1);
|
||||
|
||||
Slider slider1 = tester.widget(slider1Finder);
|
||||
Slider slider2 = tester.widget(slider2Finder);
|
||||
expect(slider1.secondaryTrackValue, slider2.value);
|
||||
|
||||
const double targetValue = 0.8;
|
||||
final Rect rect = tester.getRect(slider2Finder);
|
||||
final Offset target = Offset(rect.left + (rect.right - rect.left) * targetValue, rect.top + (rect.bottom - rect.top) / 2);
|
||||
await tester.tapAt(target);
|
||||
await tester.pump();
|
||||
|
||||
slider1 = tester.widget(slider1Finder);
|
||||
slider2 = tester.widget(slider2Finder);
|
||||
expect(slider1.secondaryTrackValue, closeTo(targetValue, 0.05));
|
||||
expect(slider1.secondaryTrackValue, slider2.value);
|
||||
});
|
||||
}
|
@ -48,6 +48,13 @@ enum _SliderType { material, adaptive }
|
||||
/// ** See code in examples/api/lib/material/slider/slider.0.dart **
|
||||
/// {@end-tool}
|
||||
///
|
||||
/// {@tool dartpad}
|
||||
/// This example shows a [Slider] widget using the [Slider.secondaryTrackValue]
|
||||
/// to show a secondary track in the slider.
|
||||
///
|
||||
/// ** See code in examples/api/lib/material/slider/slider.1.dart **
|
||||
/// {@end-tool}
|
||||
///
|
||||
/// A slider can be used to select from either a continuous or a discrete set of
|
||||
/// values. The default is to use a continuous range of values from [min] to
|
||||
/// [max]. To use discrete values, use a non-null value for [divisions], which
|
||||
@ -125,6 +132,7 @@ class Slider extends StatefulWidget {
|
||||
const Slider({
|
||||
super.key,
|
||||
required this.value,
|
||||
this.secondaryTrackValue,
|
||||
required this.onChanged,
|
||||
this.onChangeStart,
|
||||
this.onChangeEnd,
|
||||
@ -134,6 +142,7 @@ class Slider extends StatefulWidget {
|
||||
this.label,
|
||||
this.activeColor,
|
||||
this.inactiveColor,
|
||||
this.secondaryActiveColor,
|
||||
this.thumbColor,
|
||||
this.mouseCursor,
|
||||
this.semanticFormatterCallback,
|
||||
@ -146,6 +155,8 @@ class Slider extends StatefulWidget {
|
||||
assert(min <= max),
|
||||
assert(value >= min && value <= max,
|
||||
'Value $value is not between minimum $min and maximum $max'),
|
||||
assert(secondaryTrackValue == null || (secondaryTrackValue >= min && secondaryTrackValue <= max),
|
||||
'SecondaryValue $secondaryTrackValue is not between $min and $max'),
|
||||
assert(divisions == null || divisions > 0);
|
||||
|
||||
/// Creates an adaptive [Slider] based on the target platform, following
|
||||
@ -155,13 +166,15 @@ class Slider extends StatefulWidget {
|
||||
/// Creates a [CupertinoSlider] if the target platform is iOS or macOS, creates a
|
||||
/// Material Design slider otherwise.
|
||||
///
|
||||
/// If a [CupertinoSlider] is created, the following parameters are
|
||||
/// ignored: [label], [inactiveColor], [semanticFormatterCallback].
|
||||
/// If a [CupertinoSlider] is created, the following parameters are ignored:
|
||||
/// [secondaryTrackValue], [label], [inactiveColor], [secondaryActiveColor],
|
||||
/// [semanticFormatterCallback].
|
||||
///
|
||||
/// The target platform is based on the current [Theme]: [ThemeData.platform].
|
||||
const Slider.adaptive({
|
||||
super.key,
|
||||
required this.value,
|
||||
this.secondaryTrackValue,
|
||||
required this.onChanged,
|
||||
this.onChangeStart,
|
||||
this.onChangeEnd,
|
||||
@ -172,6 +185,7 @@ class Slider extends StatefulWidget {
|
||||
this.mouseCursor,
|
||||
this.activeColor,
|
||||
this.inactiveColor,
|
||||
this.secondaryActiveColor,
|
||||
this.thumbColor,
|
||||
this.semanticFormatterCallback,
|
||||
this.focusNode,
|
||||
@ -181,7 +195,10 @@ class Slider extends StatefulWidget {
|
||||
assert(min != null),
|
||||
assert(max != null),
|
||||
assert(min <= max),
|
||||
assert(value >= min && value <= max),
|
||||
assert(value >= min && value <= max,
|
||||
'Value $value is not between minimum $min and maximum $max'),
|
||||
assert(secondaryTrackValue == null || (secondaryTrackValue >= min && secondaryTrackValue <= max),
|
||||
'SecondaryValue $secondaryTrackValue is not between $min and $max'),
|
||||
assert(divisions == null || divisions > 0);
|
||||
|
||||
/// The currently selected value for this slider.
|
||||
@ -189,6 +206,17 @@ class Slider extends StatefulWidget {
|
||||
/// The slider's thumb is drawn at a position that corresponds to this value.
|
||||
final double value;
|
||||
|
||||
/// The secondary track value for this slider.
|
||||
///
|
||||
/// If not null, a secondary track using [Slider.secondaryActiveColor] color
|
||||
/// is drawn between the thumb and this value, over the inactive track.
|
||||
///
|
||||
/// If less than [Slider.value], then the secondary track is not shown.
|
||||
///
|
||||
/// It can be ideal for media scenarios such as showing the buffering progress
|
||||
/// while the [Slider.value] shows the play progress.
|
||||
final double? secondaryTrackValue;
|
||||
|
||||
/// Called during a drag when the user is selecting a new value for the slider
|
||||
/// by dragging.
|
||||
///
|
||||
@ -365,6 +393,18 @@ class Slider extends StatefulWidget {
|
||||
/// Ignored if this slider is created with [Slider.adaptive].
|
||||
final Color? inactiveColor;
|
||||
|
||||
/// The color to use for the portion of the slider track between the thumb and
|
||||
/// the [Slider.secondaryTrackValue].
|
||||
///
|
||||
/// Defaults to the [SliderThemeData.secondaryActiveTrackColor] of the current
|
||||
/// [SliderTheme].
|
||||
///
|
||||
/// Using a [SliderTheme] gives much more fine-grained control over the
|
||||
/// appearance of various components of the slider.
|
||||
///
|
||||
/// Ignored if this slider is created with [Slider.adaptive].
|
||||
final Color? secondaryActiveColor;
|
||||
|
||||
/// The color of the thumb.
|
||||
///
|
||||
/// If this color is null:
|
||||
@ -443,6 +483,7 @@ class Slider extends StatefulWidget {
|
||||
void debugFillProperties(DiagnosticPropertiesBuilder properties) {
|
||||
super.debugFillProperties(properties);
|
||||
properties.add(DoubleProperty('value', value));
|
||||
properties.add(DoubleProperty('secondaryTrackValue', secondaryTrackValue));
|
||||
properties.add(ObjectFlagProperty<ValueChanged<double>>('onChanged', onChanged, ifNull: 'disabled'));
|
||||
properties.add(ObjectFlagProperty<ValueChanged<double>>.has('onChangeStart', onChangeStart));
|
||||
properties.add(ObjectFlagProperty<ValueChanged<double>>.has('onChangeEnd', onChangeEnd));
|
||||
@ -452,6 +493,7 @@ class Slider extends StatefulWidget {
|
||||
properties.add(StringProperty('label', label));
|
||||
properties.add(ColorProperty('activeColor', activeColor));
|
||||
properties.add(ColorProperty('inactiveColor', inactiveColor));
|
||||
properties.add(ColorProperty('secondaryActiveColor', secondaryActiveColor));
|
||||
properties.add(ObjectFlagProperty<ValueChanged<double>>.has('semanticFormatterCallback', semanticFormatterCallback));
|
||||
properties.add(ObjectFlagProperty<FocusNode>.has('focusNode', focusNode));
|
||||
properties.add(FlagProperty('autofocus', value: autofocus, ifTrue: 'autofocus'));
|
||||
@ -708,8 +750,10 @@ class _SliderState extends State<Slider> with TickerProviderStateMixin {
|
||||
trackHeight: sliderTheme.trackHeight ?? defaultTrackHeight,
|
||||
activeTrackColor: widget.activeColor ?? sliderTheme.activeTrackColor ?? theme.colorScheme.primary,
|
||||
inactiveTrackColor: widget.inactiveColor ?? sliderTheme.inactiveTrackColor ?? theme.colorScheme.primary.withOpacity(0.24),
|
||||
secondaryActiveTrackColor: widget.secondaryActiveColor ?? sliderTheme.secondaryActiveTrackColor ?? theme.colorScheme.primary.withOpacity(0.54),
|
||||
disabledActiveTrackColor: sliderTheme.disabledActiveTrackColor ?? theme.colorScheme.onSurface.withOpacity(0.32),
|
||||
disabledInactiveTrackColor: sliderTheme.disabledInactiveTrackColor ?? theme.colorScheme.onSurface.withOpacity(0.12),
|
||||
disabledSecondaryActiveTrackColor: sliderTheme.disabledSecondaryActiveTrackColor ?? theme.colorScheme.onSurface.withOpacity(0.12),
|
||||
activeTickMarkColor: widget.inactiveColor ?? sliderTheme.activeTickMarkColor ?? theme.colorScheme.onPrimary.withOpacity(0.54),
|
||||
inactiveTickMarkColor: widget.activeColor ?? sliderTheme.inactiveTickMarkColor ?? theme.colorScheme.primary.withOpacity(0.54),
|
||||
disabledActiveTickMarkColor: sliderTheme.disabledActiveTickMarkColor ?? theme.colorScheme.onPrimary.withOpacity(0.12),
|
||||
@ -789,6 +833,7 @@ class _SliderState extends State<Slider> with TickerProviderStateMixin {
|
||||
child: _SliderRenderObjectWidget(
|
||||
key: _renderObjectKey,
|
||||
value: _convert(widget.value),
|
||||
secondaryTrackValue: (widget.secondaryTrackValue != null) ? _convert(widget.secondaryTrackValue!) : null,
|
||||
divisions: widget.divisions,
|
||||
label: widget.label,
|
||||
sliderTheme: sliderTheme,
|
||||
@ -852,6 +897,7 @@ class _SliderRenderObjectWidget extends LeafRenderObjectWidget {
|
||||
const _SliderRenderObjectWidget({
|
||||
super.key,
|
||||
required this.value,
|
||||
required this.secondaryTrackValue,
|
||||
required this.divisions,
|
||||
required this.label,
|
||||
required this.sliderTheme,
|
||||
@ -867,6 +913,7 @@ class _SliderRenderObjectWidget extends LeafRenderObjectWidget {
|
||||
});
|
||||
|
||||
final double value;
|
||||
final double? secondaryTrackValue;
|
||||
final int? divisions;
|
||||
final String? label;
|
||||
final SliderThemeData sliderTheme;
|
||||
@ -884,6 +931,7 @@ class _SliderRenderObjectWidget extends LeafRenderObjectWidget {
|
||||
_RenderSlider createRenderObject(BuildContext context) {
|
||||
return _RenderSlider(
|
||||
value: value,
|
||||
secondaryTrackValue: secondaryTrackValue,
|
||||
divisions: divisions,
|
||||
label: label,
|
||||
sliderTheme: sliderTheme,
|
||||
@ -909,6 +957,7 @@ class _SliderRenderObjectWidget extends LeafRenderObjectWidget {
|
||||
// setter dependent on the `divisions`.
|
||||
..divisions = divisions
|
||||
..value = value
|
||||
..secondaryTrackValue = secondaryTrackValue
|
||||
..label = label
|
||||
..sliderTheme = sliderTheme
|
||||
..textScaleFactor = textScaleFactor
|
||||
@ -930,6 +979,7 @@ class _SliderRenderObjectWidget extends LeafRenderObjectWidget {
|
||||
class _RenderSlider extends RenderBox with RelayoutWhenSystemFontsChangeMixin {
|
||||
_RenderSlider({
|
||||
required double value,
|
||||
required double? secondaryTrackValue,
|
||||
required int? divisions,
|
||||
required String? label,
|
||||
required SliderThemeData sliderTheme,
|
||||
@ -946,12 +996,14 @@ class _RenderSlider extends RenderBox with RelayoutWhenSystemFontsChangeMixin {
|
||||
required bool hovering,
|
||||
required DeviceGestureSettings gestureSettings,
|
||||
}) : assert(value != null && value >= 0.0 && value <= 1.0),
|
||||
assert(secondaryTrackValue == null || (secondaryTrackValue >= 0.0 && secondaryTrackValue <= 1.0)),
|
||||
assert(state != null),
|
||||
assert(textDirection != null),
|
||||
_platform = platform,
|
||||
_semanticFormatterCallback = semanticFormatterCallback,
|
||||
_label = label,
|
||||
_value = value,
|
||||
_secondaryTrackValue = secondaryTrackValue,
|
||||
_divisions = divisions,
|
||||
_sliderTheme = sliderTheme,
|
||||
_textScaleFactor = textScaleFactor,
|
||||
@ -1059,6 +1111,17 @@ class _RenderSlider extends RenderBox with RelayoutWhenSystemFontsChangeMixin {
|
||||
markNeedsSemanticsUpdate();
|
||||
}
|
||||
|
||||
double? get secondaryTrackValue => _secondaryTrackValue;
|
||||
double? _secondaryTrackValue;
|
||||
set secondaryTrackValue(double? newValue) {
|
||||
assert(newValue == null || (newValue >= 0.0 && newValue <= 1.0));
|
||||
if (newValue == _secondaryTrackValue) {
|
||||
return;
|
||||
}
|
||||
_secondaryTrackValue = newValue;
|
||||
markNeedsSemanticsUpdate();
|
||||
}
|
||||
|
||||
DeviceGestureSettings? get gestureSettings => _drag.gestureSettings;
|
||||
set gestureSettings(DeviceGestureSettings? gestureSettings) {
|
||||
_drag.gestureSettings = gestureSettings;
|
||||
@ -1417,17 +1480,21 @@ class _RenderSlider extends RenderBox with RelayoutWhenSystemFontsChangeMixin {
|
||||
@override
|
||||
void paint(PaintingContext context, Offset offset) {
|
||||
final double value = _state.positionController.value;
|
||||
final double? secondaryValue = _secondaryTrackValue;
|
||||
|
||||
// The visual position is the position of the thumb from 0 to 1 from left
|
||||
// to right. In left to right, this is the same as the value, but it is
|
||||
// reversed for right to left text.
|
||||
final double visualPosition;
|
||||
final double? secondaryVisualPosition;
|
||||
switch (textDirection) {
|
||||
case TextDirection.rtl:
|
||||
visualPosition = 1.0 - value;
|
||||
secondaryVisualPosition = (secondaryValue != null) ? (1.0 - secondaryValue) : null;
|
||||
break;
|
||||
case TextDirection.ltr:
|
||||
visualPosition = value;
|
||||
secondaryVisualPosition = (secondaryValue != null) ? secondaryValue : null;
|
||||
break;
|
||||
}
|
||||
|
||||
@ -1438,6 +1505,7 @@ class _RenderSlider extends RenderBox with RelayoutWhenSystemFontsChangeMixin {
|
||||
isDiscrete: isDiscrete,
|
||||
);
|
||||
final Offset thumbCenter = Offset(trackRect.left + visualPosition * trackRect.width, trackRect.center.dy);
|
||||
final Offset? secondaryOffset = (secondaryVisualPosition != null) ? Offset(trackRect.left + secondaryVisualPosition * trackRect.width, trackRect.center.dy) : null;
|
||||
|
||||
_sliderTheme.trackShape!.paint(
|
||||
context,
|
||||
@ -1447,6 +1515,7 @@ class _RenderSlider extends RenderBox with RelayoutWhenSystemFontsChangeMixin {
|
||||
enableAnimation: _enableAnimation,
|
||||
textDirection: _textDirection,
|
||||
thumbCenter: thumbCenter,
|
||||
secondaryOffset: secondaryOffset,
|
||||
isDiscrete: isDiscrete,
|
||||
isEnabled: isInteractive,
|
||||
);
|
||||
|
@ -266,8 +266,10 @@ class SliderThemeData with Diagnosticable {
|
||||
this.trackHeight,
|
||||
this.activeTrackColor,
|
||||
this.inactiveTrackColor,
|
||||
this.secondaryActiveTrackColor,
|
||||
this.disabledActiveTrackColor,
|
||||
this.disabledInactiveTrackColor,
|
||||
this.disabledSecondaryActiveTrackColor,
|
||||
this.activeTickMarkColor,
|
||||
this.inactiveTickMarkColor,
|
||||
this.disabledActiveTickMarkColor,
|
||||
@ -317,8 +319,10 @@ class SliderThemeData with Diagnosticable {
|
||||
// component Colors (with opacity) from base colors.
|
||||
const int activeTrackAlpha = 0xff;
|
||||
const int inactiveTrackAlpha = 0x3d; // 24% opacity
|
||||
const int secondaryActiveTrackAlpha = 0x8a; // 54% opacity
|
||||
const int disabledActiveTrackAlpha = 0x52; // 32% opacity
|
||||
const int disabledInactiveTrackAlpha = 0x1f; // 12% opacity
|
||||
const int disabledSecondaryActiveTrackAlpha = 0x1f; // 12% opacity
|
||||
const int activeTickMarkAlpha = 0x8a; // 54% opacity
|
||||
const int inactiveTickMarkAlpha = 0x8a; // 54% opacity
|
||||
const int disabledActiveTickMarkAlpha = 0x1f; // 12% opacity
|
||||
@ -332,8 +336,10 @@ class SliderThemeData with Diagnosticable {
|
||||
trackHeight: 2.0,
|
||||
activeTrackColor: primaryColor.withAlpha(activeTrackAlpha),
|
||||
inactiveTrackColor: primaryColor.withAlpha(inactiveTrackAlpha),
|
||||
secondaryActiveTrackColor: primaryColor.withAlpha(secondaryActiveTrackAlpha),
|
||||
disabledActiveTrackColor: primaryColorDark.withAlpha(disabledActiveTrackAlpha),
|
||||
disabledInactiveTrackColor: primaryColorDark.withAlpha(disabledInactiveTrackAlpha),
|
||||
disabledSecondaryActiveTrackColor: primaryColorDark.withAlpha(disabledSecondaryActiveTrackAlpha),
|
||||
activeTickMarkColor: primaryColorLight.withAlpha(activeTickMarkAlpha),
|
||||
inactiveTickMarkColor: primaryColor.withAlpha(inactiveTickMarkAlpha),
|
||||
disabledActiveTickMarkColor: primaryColorLight.withAlpha(disabledActiveTickMarkAlpha),
|
||||
@ -368,10 +374,18 @@ class SliderThemeData with Diagnosticable {
|
||||
/// [Slider.max] position.
|
||||
final Color? inactiveTrackColor;
|
||||
|
||||
/// The color of the [Slider] track between the current thumb position and the
|
||||
/// [Slider.secondaryTrackValue] position.
|
||||
final Color? secondaryActiveTrackColor;
|
||||
|
||||
/// The color of the [Slider] track between the [Slider.min] position and the
|
||||
/// current thumb position when the [Slider] is disabled.
|
||||
final Color? disabledActiveTrackColor;
|
||||
|
||||
/// The color of the [Slider] track between the current thumb position and the
|
||||
/// [Slider.secondaryTrackValue] position when the [Slider] is disabled.
|
||||
final Color? disabledSecondaryActiveTrackColor;
|
||||
|
||||
/// The color of the [Slider] track between the current thumb position and the
|
||||
/// [Slider.max] position when the [Slider] is disabled.
|
||||
final Color? disabledInactiveTrackColor;
|
||||
@ -573,8 +587,10 @@ class SliderThemeData with Diagnosticable {
|
||||
double? trackHeight,
|
||||
Color? activeTrackColor,
|
||||
Color? inactiveTrackColor,
|
||||
Color? secondaryActiveTrackColor,
|
||||
Color? disabledActiveTrackColor,
|
||||
Color? disabledInactiveTrackColor,
|
||||
Color? disabledSecondaryActiveTrackColor,
|
||||
Color? activeTickMarkColor,
|
||||
Color? inactiveTickMarkColor,
|
||||
Color? disabledActiveTickMarkColor,
|
||||
@ -603,8 +619,10 @@ class SliderThemeData with Diagnosticable {
|
||||
trackHeight: trackHeight ?? this.trackHeight,
|
||||
activeTrackColor: activeTrackColor ?? this.activeTrackColor,
|
||||
inactiveTrackColor: inactiveTrackColor ?? this.inactiveTrackColor,
|
||||
secondaryActiveTrackColor: secondaryActiveTrackColor ?? this.secondaryActiveTrackColor,
|
||||
disabledActiveTrackColor: disabledActiveTrackColor ?? this.disabledActiveTrackColor,
|
||||
disabledInactiveTrackColor: disabledInactiveTrackColor ?? this.disabledInactiveTrackColor,
|
||||
disabledSecondaryActiveTrackColor: disabledSecondaryActiveTrackColor ?? this.disabledSecondaryActiveTrackColor,
|
||||
activeTickMarkColor: activeTickMarkColor ?? this.activeTickMarkColor,
|
||||
inactiveTickMarkColor: inactiveTickMarkColor ?? this.inactiveTickMarkColor,
|
||||
disabledActiveTickMarkColor: disabledActiveTickMarkColor ?? this.disabledActiveTickMarkColor,
|
||||
@ -644,8 +662,10 @@ class SliderThemeData with Diagnosticable {
|
||||
trackHeight: lerpDouble(a.trackHeight, b.trackHeight, t),
|
||||
activeTrackColor: Color.lerp(a.activeTrackColor, b.activeTrackColor, t),
|
||||
inactiveTrackColor: Color.lerp(a.inactiveTrackColor, b.inactiveTrackColor, t),
|
||||
secondaryActiveTrackColor: Color.lerp(a.secondaryActiveTrackColor, b.secondaryActiveTrackColor, t),
|
||||
disabledActiveTrackColor: Color.lerp(a.disabledActiveTrackColor, b.disabledActiveTrackColor, t),
|
||||
disabledInactiveTrackColor: Color.lerp(a.disabledInactiveTrackColor, b.disabledInactiveTrackColor, t),
|
||||
disabledSecondaryActiveTrackColor: Color.lerp(a.disabledSecondaryActiveTrackColor, b.disabledSecondaryActiveTrackColor, t),
|
||||
activeTickMarkColor: Color.lerp(a.activeTickMarkColor, b.activeTickMarkColor, t),
|
||||
inactiveTickMarkColor: Color.lerp(a.inactiveTickMarkColor, b.inactiveTickMarkColor, t),
|
||||
disabledActiveTickMarkColor: Color.lerp(a.disabledActiveTickMarkColor, b.disabledActiveTickMarkColor, t),
|
||||
@ -677,8 +697,10 @@ class SliderThemeData with Diagnosticable {
|
||||
trackHeight,
|
||||
activeTrackColor,
|
||||
inactiveTrackColor,
|
||||
secondaryActiveTrackColor,
|
||||
disabledActiveTrackColor,
|
||||
disabledInactiveTrackColor,
|
||||
disabledSecondaryActiveTrackColor,
|
||||
activeTickMarkColor,
|
||||
inactiveTickMarkColor,
|
||||
disabledActiveTickMarkColor,
|
||||
@ -691,9 +713,9 @@ class SliderThemeData with Diagnosticable {
|
||||
overlayShape,
|
||||
tickMarkShape,
|
||||
thumbShape,
|
||||
trackShape,
|
||||
valueIndicatorShape,
|
||||
Object.hash(
|
||||
trackShape,
|
||||
valueIndicatorShape,
|
||||
rangeTickMarkShape,
|
||||
rangeThumbShape,
|
||||
rangeTrackShape,
|
||||
@ -718,8 +740,10 @@ class SliderThemeData with Diagnosticable {
|
||||
&& other.trackHeight == trackHeight
|
||||
&& other.activeTrackColor == activeTrackColor
|
||||
&& other.inactiveTrackColor == inactiveTrackColor
|
||||
&& other.secondaryActiveTrackColor == secondaryActiveTrackColor
|
||||
&& other.disabledActiveTrackColor == disabledActiveTrackColor
|
||||
&& other.disabledInactiveTrackColor == disabledInactiveTrackColor
|
||||
&& other.disabledSecondaryActiveTrackColor == disabledSecondaryActiveTrackColor
|
||||
&& other.activeTickMarkColor == activeTickMarkColor
|
||||
&& other.inactiveTickMarkColor == inactiveTickMarkColor
|
||||
&& other.disabledActiveTickMarkColor == disabledActiveTickMarkColor
|
||||
@ -752,8 +776,10 @@ class SliderThemeData with Diagnosticable {
|
||||
properties.add(DoubleProperty('trackHeight', trackHeight, defaultValue: defaultData.trackHeight));
|
||||
properties.add(ColorProperty('activeTrackColor', activeTrackColor, defaultValue: defaultData.activeTrackColor));
|
||||
properties.add(ColorProperty('inactiveTrackColor', inactiveTrackColor, defaultValue: defaultData.inactiveTrackColor));
|
||||
properties.add(ColorProperty('secondaryActiveTrackColor', secondaryActiveTrackColor, defaultValue: defaultData.secondaryActiveTrackColor));
|
||||
properties.add(ColorProperty('disabledActiveTrackColor', disabledActiveTrackColor, defaultValue: defaultData.disabledActiveTrackColor));
|
||||
properties.add(ColorProperty('disabledInactiveTrackColor', disabledInactiveTrackColor, defaultValue: defaultData.disabledInactiveTrackColor));
|
||||
properties.add(ColorProperty('disabledSecondaryActiveTrackColor', disabledSecondaryActiveTrackColor, defaultValue: defaultData.disabledSecondaryActiveTrackColor));
|
||||
properties.add(ColorProperty('activeTickMarkColor', activeTickMarkColor, defaultValue: defaultData.activeTickMarkColor));
|
||||
properties.add(ColorProperty('inactiveTickMarkColor', inactiveTickMarkColor, defaultValue: defaultData.inactiveTickMarkColor));
|
||||
properties.add(ColorProperty('disabledActiveTickMarkColor', disabledActiveTickMarkColor, defaultValue: defaultData.disabledActiveTickMarkColor));
|
||||
@ -1047,6 +1073,11 @@ abstract class SliderTrackShape {
|
||||
/// relative to the origin of the [PaintingContext.canvas]. It can be used as
|
||||
/// the point that divides the track into 2 segments.
|
||||
///
|
||||
/// The `secondaryOffset` argument is the offset of the secondary value
|
||||
/// relative to the origin of the [PaintingContext.canvas].
|
||||
///
|
||||
/// If not null, the track is divided into 3 segments.
|
||||
///
|
||||
/// {@macro flutter.material.SliderTickMarkShape.getPreferredSize.isEnabled}
|
||||
///
|
||||
/// {@macro flutter.material.SliderComponentShape.paint.isDiscrete}
|
||||
@ -1068,6 +1099,7 @@ abstract class SliderTrackShape {
|
||||
required SliderThemeData sliderTheme,
|
||||
required Animation<double> enableAnimation,
|
||||
required Offset thumbCenter,
|
||||
Offset? secondaryOffset,
|
||||
bool isEnabled,
|
||||
bool isDiscrete,
|
||||
required TextDirection textDirection,
|
||||
@ -1534,6 +1566,7 @@ class RectangularSliderTrackShape extends SliderTrackShape with BaseSliderTrackS
|
||||
required Animation<double> enableAnimation,
|
||||
required TextDirection textDirection,
|
||||
required Offset thumbCenter,
|
||||
Offset? secondaryOffset,
|
||||
bool isDiscrete = false,
|
||||
bool isEnabled = false,
|
||||
}) {
|
||||
@ -1593,6 +1626,25 @@ class RectangularSliderTrackShape extends SliderTrackShape with BaseSliderTrackS
|
||||
if (!rightTrackSegment.isEmpty) {
|
||||
context.canvas.drawRect(rightTrackSegment, rightTrackPaint);
|
||||
}
|
||||
|
||||
final bool showSecondaryTrack = (secondaryOffset != null) &&
|
||||
((textDirection == TextDirection.ltr)
|
||||
? (secondaryOffset.dx > thumbCenter.dx)
|
||||
: (secondaryOffset.dx < thumbCenter.dx));
|
||||
|
||||
if (showSecondaryTrack) {
|
||||
final ColorTween secondaryTrackColorTween = ColorTween(begin: sliderTheme.disabledSecondaryActiveTrackColor, end: sliderTheme.secondaryActiveTrackColor);
|
||||
final Paint secondaryTrackPaint = Paint()..color = secondaryTrackColorTween.evaluate(enableAnimation)!;
|
||||
final Rect secondaryTrackSegment = Rect.fromLTRB(
|
||||
(textDirection == TextDirection.ltr) ? thumbCenter.dx : secondaryOffset.dx,
|
||||
trackRect.top,
|
||||
(textDirection == TextDirection.ltr) ? secondaryOffset.dx : thumbCenter.dx,
|
||||
trackRect.bottom,
|
||||
);
|
||||
if (!secondaryTrackSegment.isEmpty) {
|
||||
context.canvas.drawRect(secondaryTrackSegment, secondaryTrackPaint);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1635,6 +1687,7 @@ class RoundedRectSliderTrackShape extends SliderTrackShape with BaseSliderTrackS
|
||||
required Animation<double> enableAnimation,
|
||||
required TextDirection textDirection,
|
||||
required Offset thumbCenter,
|
||||
Offset? secondaryOffset,
|
||||
bool isDiscrete = false,
|
||||
bool isEnabled = false,
|
||||
double additionalActiveTrackHeight = 2,
|
||||
@ -1709,6 +1762,41 @@ class RoundedRectSliderTrackShape extends SliderTrackShape with BaseSliderTrackS
|
||||
),
|
||||
rightTrackPaint,
|
||||
);
|
||||
|
||||
final bool showSecondaryTrack = (secondaryOffset != null) &&
|
||||
((textDirection == TextDirection.ltr)
|
||||
? (secondaryOffset.dx > thumbCenter.dx)
|
||||
: (secondaryOffset.dx < thumbCenter.dx));
|
||||
|
||||
if (showSecondaryTrack) {
|
||||
final ColorTween secondaryTrackColorTween = ColorTween(begin: sliderTheme.disabledSecondaryActiveTrackColor, end: sliderTheme.secondaryActiveTrackColor);
|
||||
final Paint secondaryTrackPaint = Paint()..color = secondaryTrackColorTween.evaluate(enableAnimation)!;
|
||||
if (textDirection == TextDirection.ltr) {
|
||||
context.canvas.drawRRect(
|
||||
RRect.fromLTRBAndCorners(
|
||||
thumbCenter.dx,
|
||||
trackRect.top,
|
||||
secondaryOffset.dx,
|
||||
trackRect.bottom,
|
||||
topRight: trackRadius,
|
||||
bottomRight: trackRadius,
|
||||
),
|
||||
secondaryTrackPaint,
|
||||
);
|
||||
} else {
|
||||
context.canvas.drawRRect(
|
||||
RRect.fromLTRBAndCorners(
|
||||
secondaryOffset.dx,
|
||||
trackRect.top,
|
||||
thumbCenter.dx,
|
||||
trackRect.bottom,
|
||||
topLeft: trackRadius,
|
||||
bottomLeft: trackRadius,
|
||||
),
|
||||
secondaryTrackPaint,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -631,6 +631,7 @@ void main() {
|
||||
try {
|
||||
const Color customColor1 = Color(0xcafefeed);
|
||||
const Color customColor2 = Color(0xdeadbeef);
|
||||
const Color customColor3 = Color(0xdecaface);
|
||||
final ThemeData theme = ThemeData(
|
||||
platform: TargetPlatform.android,
|
||||
primarySwatch: Colors.blue,
|
||||
@ -647,6 +648,8 @@ void main() {
|
||||
overlayColor: Color(0xff000010),
|
||||
thumbColor: Color(0xff000011),
|
||||
valueIndicatorColor: Color(0xff000012),
|
||||
disabledSecondaryActiveTrackColor: Color(0xff000013),
|
||||
secondaryActiveTrackColor: Color(0xff000014),
|
||||
),
|
||||
);
|
||||
final SliderThemeData sliderTheme = theme.sliderTheme;
|
||||
@ -654,6 +657,7 @@ void main() {
|
||||
Widget buildApp({
|
||||
Color? activeColor,
|
||||
Color? inactiveColor,
|
||||
Color? secondaryActiveColor,
|
||||
int? divisions,
|
||||
bool enabled = true,
|
||||
}) {
|
||||
@ -671,10 +675,12 @@ void main() {
|
||||
data: theme,
|
||||
child: Slider(
|
||||
value: value,
|
||||
secondaryTrackValue: 0.75,
|
||||
label: '$value',
|
||||
divisions: divisions,
|
||||
activeColor: activeColor,
|
||||
inactiveColor: inactiveColor,
|
||||
secondaryActiveColor: secondaryActiveColor,
|
||||
onChanged: onChanged,
|
||||
),
|
||||
),
|
||||
@ -690,47 +696,61 @@ void main() {
|
||||
final RenderBox valueIndicatorBox = tester.renderObject(find.byType(Overlay));
|
||||
|
||||
// Check default theme for enabled widget.
|
||||
expect(material, paints..rrect(color: sliderTheme.activeTrackColor)..rrect(color: sliderTheme.inactiveTrackColor));
|
||||
expect(material, paints..rrect(color: sliderTheme.activeTrackColor)..rrect(color: sliderTheme.inactiveTrackColor)..rrect(color: sliderTheme.secondaryActiveTrackColor));
|
||||
expect(material, paints..shadow(color: const Color(0xff000000)));
|
||||
expect(material, paints..circle(color: sliderTheme.thumbColor));
|
||||
expect(material, isNot(paints..circle(color: sliderTheme.disabledThumbColor)));
|
||||
expect(material, isNot(paints..rrect(color: sliderTheme.disabledActiveTrackColor)));
|
||||
expect(material, isNot(paints..rrect(color: sliderTheme.disabledInactiveTrackColor)));
|
||||
expect(material, isNot(paints..rrect(color: sliderTheme.disabledSecondaryActiveTrackColor)));
|
||||
expect(material, isNot(paints..circle(color: sliderTheme.activeTickMarkColor)));
|
||||
expect(material, isNot(paints..circle(color: sliderTheme.inactiveTickMarkColor)));
|
||||
|
||||
// Test setting only the activeColor.
|
||||
await tester.pumpWidget(buildApp(activeColor: customColor1));
|
||||
expect(material, paints..rrect(color: customColor1)..rrect(color: sliderTheme.inactiveTrackColor));
|
||||
expect(material, paints..rrect(color: customColor1)..rrect(color: sliderTheme.inactiveTrackColor)..rrect(color: sliderTheme.secondaryActiveTrackColor));
|
||||
expect(material, paints..shadow(color: Colors.black));
|
||||
expect(material, paints..circle(color: customColor1));
|
||||
expect(material, isNot(paints..circle(color: sliderTheme.thumbColor)));
|
||||
expect(material, isNot(paints..circle(color: sliderTheme.disabledThumbColor)));
|
||||
expect(material, isNot(paints..rrect(color: sliderTheme.disabledActiveTrackColor)));
|
||||
expect(material, isNot(paints..rrect(color: sliderTheme.disabledInactiveTrackColor)));
|
||||
expect(material, isNot(paints..rrect(color: sliderTheme.disabledSecondaryActiveTrackColor)));
|
||||
|
||||
// Test setting only the inactiveColor.
|
||||
await tester.pumpWidget(buildApp(inactiveColor: customColor1));
|
||||
expect(material, paints..rrect(color: sliderTheme.activeTrackColor)..rrect(color: customColor1));
|
||||
expect(material, paints..rrect(color: sliderTheme.activeTrackColor)..rrect(color: customColor1)..rrect(color: sliderTheme.secondaryActiveTrackColor));
|
||||
expect(material, paints..shadow(color: Colors.black));
|
||||
expect(material, paints..circle(color: sliderTheme.thumbColor));
|
||||
expect(material, isNot(paints..circle(color: sliderTheme.disabledThumbColor)));
|
||||
expect(material, isNot(paints..rrect(color: sliderTheme.disabledActiveTrackColor)));
|
||||
expect(material, isNot(paints..rrect(color: sliderTheme.disabledInactiveTrackColor)));
|
||||
expect(material, isNot(paints..rrect(color: sliderTheme.disabledSecondaryActiveTrackColor)));
|
||||
|
||||
// Test setting both activeColor and inactiveColor.
|
||||
await tester.pumpWidget(buildApp(activeColor: customColor1, inactiveColor: customColor2));
|
||||
expect(material, paints..rrect(color: customColor1)..rrect(color: customColor2));
|
||||
// Test setting only the secondaryActiveColor.
|
||||
await tester.pumpWidget(buildApp(secondaryActiveColor: customColor1));
|
||||
expect(material, paints..rrect(color: sliderTheme.activeTrackColor)..rrect(color: sliderTheme.inactiveTrackColor)..rrect(color: customColor1));
|
||||
expect(material, paints..shadow(color: Colors.black));
|
||||
expect(material, paints..circle(color: sliderTheme.thumbColor));
|
||||
expect(material, isNot(paints..circle(color: sliderTheme.disabledThumbColor)));
|
||||
expect(material, isNot(paints..rrect(color: sliderTheme.disabledActiveTrackColor)));
|
||||
expect(material, isNot(paints..rrect(color: sliderTheme.disabledInactiveTrackColor)));
|
||||
expect(material, isNot(paints..rrect(color: sliderTheme.disabledSecondaryActiveTrackColor)));
|
||||
|
||||
// Test setting both activeColor, inactiveColor, and secondaryActiveColor.
|
||||
await tester.pumpWidget(buildApp(activeColor: customColor1, inactiveColor: customColor2, secondaryActiveColor: customColor3));
|
||||
expect(material, paints..rrect(color: customColor1)..rrect(color: customColor2)..rrect(color: customColor3));
|
||||
expect(material, paints..shadow(color: Colors.black));
|
||||
expect(material, paints..circle(color: customColor1));
|
||||
expect(material, isNot(paints..circle(color: sliderTheme.thumbColor)));
|
||||
expect(material, isNot(paints..circle(color: sliderTheme.disabledThumbColor)));
|
||||
expect(material, isNot(paints..rrect(color: sliderTheme.disabledActiveTrackColor)));
|
||||
expect(material, isNot(paints..rrect(color: sliderTheme.disabledInactiveTrackColor)));
|
||||
expect(material, isNot(paints..rrect(color: sliderTheme.disabledSecondaryActiveTrackColor)));
|
||||
|
||||
// Test colors for discrete slider.
|
||||
await tester.pumpWidget(buildApp(divisions: 3));
|
||||
expect(material, paints..rrect(color: sliderTheme.activeTrackColor)..rrect(color: sliderTheme.inactiveTrackColor));
|
||||
expect(material, paints..rrect(color: sliderTheme.activeTrackColor)..rrect(color: sliderTheme.inactiveTrackColor)..rrect(color: sliderTheme.secondaryActiveTrackColor));
|
||||
expect(
|
||||
material,
|
||||
paints
|
||||
@ -744,14 +764,16 @@ void main() {
|
||||
expect(material, isNot(paints..circle(color: sliderTheme.disabledThumbColor)));
|
||||
expect(material, isNot(paints..rrect(color: sliderTheme.disabledActiveTrackColor)));
|
||||
expect(material, isNot(paints..rrect(color: sliderTheme.disabledInactiveTrackColor)));
|
||||
expect(material, isNot(paints..rrect(color: sliderTheme.disabledSecondaryActiveTrackColor)));
|
||||
|
||||
// Test colors for discrete slider with inactiveColor and activeColor set.
|
||||
await tester.pumpWidget(buildApp(
|
||||
activeColor: customColor1,
|
||||
inactiveColor: customColor2,
|
||||
secondaryActiveColor: customColor3,
|
||||
divisions: 3,
|
||||
));
|
||||
expect(material, paints..rrect(color: customColor1)..rrect(color: customColor2));
|
||||
expect(material, paints..rrect(color: customColor1)..rrect(color: customColor2)..rrect(color: customColor3));
|
||||
expect(
|
||||
material,
|
||||
paints
|
||||
@ -766,6 +788,7 @@ void main() {
|
||||
expect(material, isNot(paints..circle(color: sliderTheme.disabledThumbColor)));
|
||||
expect(material, isNot(paints..rrect(color: sliderTheme.disabledActiveTrackColor)));
|
||||
expect(material, isNot(paints..rrect(color: sliderTheme.disabledInactiveTrackColor)));
|
||||
expect(material, isNot(paints..rrect(color: sliderTheme.disabledSecondaryActiveTrackColor)));
|
||||
expect(material, isNot(paints..circle(color: sliderTheme.activeTickMarkColor)));
|
||||
expect(material, isNot(paints..circle(color: sliderTheme.inactiveTickMarkColor)));
|
||||
|
||||
@ -776,25 +799,29 @@ void main() {
|
||||
material,
|
||||
paints
|
||||
..rrect(color: sliderTheme.disabledActiveTrackColor)
|
||||
..rrect(color: sliderTheme.disabledInactiveTrackColor),
|
||||
..rrect(color: sliderTheme.disabledInactiveTrackColor)
|
||||
..rrect(color: sliderTheme.disabledSecondaryActiveTrackColor),
|
||||
);
|
||||
expect(material, paints..shadow(color: Colors.black)..circle(color: sliderTheme.disabledThumbColor));
|
||||
expect(material, isNot(paints..circle(color: sliderTheme.thumbColor)));
|
||||
expect(material, isNot(paints..rrect(color: sliderTheme.activeTrackColor)));
|
||||
expect(material, isNot(paints..rrect(color: sliderTheme.inactiveTrackColor)));
|
||||
expect(material, isNot(paints..rrect(color: sliderTheme.secondaryActiveTrackColor)));
|
||||
|
||||
// Test setting the activeColor and inactiveColor for disabled widget.
|
||||
await tester.pumpWidget(buildApp(activeColor: customColor1, inactiveColor: customColor2, enabled: false));
|
||||
// Test setting the activeColor, inactiveColor and secondaryActiveColor for disabled widget.
|
||||
await tester.pumpWidget(buildApp(activeColor: customColor1, inactiveColor: customColor2, secondaryActiveColor: customColor3, enabled: false));
|
||||
expect(
|
||||
material,
|
||||
paints
|
||||
..rrect(color: sliderTheme.disabledActiveTrackColor)
|
||||
..rrect(color: sliderTheme.disabledInactiveTrackColor),
|
||||
..rrect(color: sliderTheme.disabledInactiveTrackColor)
|
||||
..rrect(color: sliderTheme.disabledSecondaryActiveTrackColor),
|
||||
);
|
||||
expect(material, paints..circle(color: sliderTheme.disabledThumbColor));
|
||||
expect(material, isNot(paints..circle(color: sliderTheme.thumbColor)));
|
||||
expect(material, isNot(paints..rrect(color: sliderTheme.activeTrackColor)));
|
||||
expect(material, isNot(paints..rrect(color: sliderTheme.inactiveTrackColor)));
|
||||
expect(material, isNot(paints..rrect(color: sliderTheme.secondaryActiveTrackColor)));
|
||||
|
||||
// Test that the default value indicator has the right colors.
|
||||
await tester.pumpWidget(buildApp(divisions: 3));
|
||||
@ -2813,10 +2840,12 @@ void main() {
|
||||
activeColor: Colors.blue,
|
||||
divisions: 10,
|
||||
inactiveColor: Colors.grey,
|
||||
secondaryActiveColor: Colors.blueGrey,
|
||||
label: 'Set a value',
|
||||
max: 100.0,
|
||||
onChanged: null,
|
||||
value: 50.0,
|
||||
secondaryTrackValue: 75.0,
|
||||
).debugFillProperties(builder);
|
||||
|
||||
final List<String> description = builder.properties
|
||||
@ -2825,6 +2854,7 @@ void main() {
|
||||
|
||||
expect(description, <String>[
|
||||
'value: 50.0',
|
||||
'secondaryTrackValue: 75.0',
|
||||
'disabled',
|
||||
'min: 0.0',
|
||||
'max: 100.0',
|
||||
@ -2832,6 +2862,7 @@ void main() {
|
||||
'label: "Set a value"',
|
||||
'activeColor: MaterialColor(primary value: Color(0xff2196f3))',
|
||||
'inactiveColor: MaterialColor(primary value: Color(0xff9e9e9e))',
|
||||
'secondaryActiveColor: MaterialColor(primary value: Color(0xff607d8b))',
|
||||
]);
|
||||
});
|
||||
|
||||
|
@ -34,17 +34,19 @@ void main() {
|
||||
trackHeight: 7.0,
|
||||
activeTrackColor: Color(0xFF000001),
|
||||
inactiveTrackColor: Color(0xFF000002),
|
||||
disabledActiveTrackColor: Color(0xFF000003),
|
||||
disabledInactiveTrackColor: Color(0xFF000004),
|
||||
activeTickMarkColor: Color(0xFF000005),
|
||||
inactiveTickMarkColor: Color(0xFF000006),
|
||||
disabledActiveTickMarkColor: Color(0xFF000007),
|
||||
disabledInactiveTickMarkColor: Color(0xFF000008),
|
||||
thumbColor: Color(0xFF000009),
|
||||
overlappingShapeStrokeColor: Color(0xFF000010),
|
||||
disabledThumbColor: Color(0xFF000011),
|
||||
overlayColor: Color(0xFF000012),
|
||||
valueIndicatorColor: Color(0xFF000013),
|
||||
secondaryActiveTrackColor: Color(0xFF000003),
|
||||
disabledActiveTrackColor: Color(0xFF000004),
|
||||
disabledInactiveTrackColor: Color(0xFF000005),
|
||||
disabledSecondaryActiveTrackColor: Color(0xFF000006),
|
||||
activeTickMarkColor: Color(0xFF000007),
|
||||
inactiveTickMarkColor: Color(0xFF000008),
|
||||
disabledActiveTickMarkColor: Color(0xFF000009),
|
||||
disabledInactiveTickMarkColor: Color(0xFF000010),
|
||||
thumbColor: Color(0xFF000011),
|
||||
overlappingShapeStrokeColor: Color(0xFF000012),
|
||||
disabledThumbColor: Color(0xFF000013),
|
||||
overlayColor: Color(0xFF000014),
|
||||
valueIndicatorColor: Color(0xFF000015),
|
||||
overlayShape: RoundSliderOverlayShape(),
|
||||
tickMarkShape: RoundSliderTickMarkShape(),
|
||||
thumbShape: RoundSliderThumbShape(),
|
||||
@ -68,17 +70,19 @@ void main() {
|
||||
'trackHeight: 7.0',
|
||||
'activeTrackColor: Color(0xff000001)',
|
||||
'inactiveTrackColor: Color(0xff000002)',
|
||||
'disabledActiveTrackColor: Color(0xff000003)',
|
||||
'disabledInactiveTrackColor: Color(0xff000004)',
|
||||
'activeTickMarkColor: Color(0xff000005)',
|
||||
'inactiveTickMarkColor: Color(0xff000006)',
|
||||
'disabledActiveTickMarkColor: Color(0xff000007)',
|
||||
'disabledInactiveTickMarkColor: Color(0xff000008)',
|
||||
'thumbColor: Color(0xff000009)',
|
||||
'overlappingShapeStrokeColor: Color(0xff000010)',
|
||||
'disabledThumbColor: Color(0xff000011)',
|
||||
'overlayColor: Color(0xff000012)',
|
||||
'valueIndicatorColor: Color(0xff000013)',
|
||||
'secondaryActiveTrackColor: Color(0xff000003)',
|
||||
'disabledActiveTrackColor: Color(0xff000004)',
|
||||
'disabledInactiveTrackColor: Color(0xff000005)',
|
||||
'disabledSecondaryActiveTrackColor: Color(0xff000006)',
|
||||
'activeTickMarkColor: Color(0xff000007)',
|
||||
'inactiveTickMarkColor: Color(0xff000008)',
|
||||
'disabledActiveTickMarkColor: Color(0xff000009)',
|
||||
'disabledInactiveTickMarkColor: Color(0xff000010)',
|
||||
'thumbColor: Color(0xff000011)',
|
||||
'overlappingShapeStrokeColor: Color(0xff000012)',
|
||||
'disabledThumbColor: Color(0xff000013)',
|
||||
'overlayColor: Color(0xff000014)',
|
||||
'valueIndicatorColor: Color(0xff000015)',
|
||||
"overlayShape: Instance of 'RoundSliderOverlayShape'",
|
||||
"tickMarkShape: Instance of 'RoundSliderTickMarkShape'",
|
||||
"thumbShape: Instance of 'RoundSliderThumbShape'",
|
||||
@ -103,16 +107,18 @@ void main() {
|
||||
final SliderThemeData customTheme = sliderTheme.copyWith(
|
||||
activeTrackColor: Colors.purple,
|
||||
inactiveTrackColor: Colors.purple.withAlpha(0x3d),
|
||||
secondaryActiveTrackColor: Colors.purple.withAlpha(0x8a),
|
||||
);
|
||||
|
||||
await tester.pumpWidget(_buildApp(sliderTheme, value: 0.5, enabled: false));
|
||||
await tester.pumpWidget(_buildApp(sliderTheme, value: 0.5, secondaryTrackValue: 0.75, enabled: false));
|
||||
final MaterialInkController material = Material.of(tester.element(find.byType(Slider)))!;
|
||||
|
||||
expect(
|
||||
material,
|
||||
paints
|
||||
..rrect(color: customTheme.disabledActiveTrackColor)
|
||||
..rrect(color: customTheme.disabledInactiveTrackColor),
|
||||
..rrect(color: customTheme.disabledInactiveTrackColor)
|
||||
..rrect(color: customTheme.disabledSecondaryActiveTrackColor),
|
||||
);
|
||||
});
|
||||
|
||||
@ -125,16 +131,18 @@ void main() {
|
||||
final SliderThemeData customTheme = sliderTheme.copyWith(
|
||||
activeTrackColor: Colors.purple,
|
||||
inactiveTrackColor: Colors.purple.withAlpha(0x3d),
|
||||
secondaryActiveTrackColor: Colors.purple.withAlpha(0x8a),
|
||||
);
|
||||
|
||||
await tester.pumpWidget(_buildApp(sliderTheme, value: 0.5, enabled: false));
|
||||
await tester.pumpWidget(_buildApp(sliderTheme, value: 0.5, secondaryTrackValue: 0.75, enabled: false));
|
||||
final MaterialInkController material = Material.of(tester.element(find.byType(Slider)))!;
|
||||
|
||||
expect(
|
||||
material,
|
||||
paints
|
||||
..rrect(color: customTheme.disabledActiveTrackColor)
|
||||
..rrect(color: customTheme.disabledInactiveTrackColor),
|
||||
..rrect(color: customTheme.disabledInactiveTrackColor)
|
||||
..rrect(color: customTheme.disabledSecondaryActiveTrackColor),
|
||||
);
|
||||
});
|
||||
|
||||
@ -153,8 +161,10 @@ void main() {
|
||||
|
||||
expect(sliderTheme.activeTrackColor, equals(customColor1.withAlpha(0xff)));
|
||||
expect(sliderTheme.inactiveTrackColor, equals(customColor1.withAlpha(0x3d)));
|
||||
expect(sliderTheme.secondaryActiveTrackColor, equals(customColor1.withAlpha(0x8a)));
|
||||
expect(sliderTheme.disabledActiveTrackColor, equals(customColor2.withAlpha(0x52)));
|
||||
expect(sliderTheme.disabledInactiveTrackColor, equals(customColor2.withAlpha(0x1f)));
|
||||
expect(sliderTheme.disabledSecondaryActiveTrackColor, equals(customColor2.withAlpha(0x1f)));
|
||||
expect(sliderTheme.activeTickMarkColor, equals(customColor3.withAlpha(0x8a)));
|
||||
expect(sliderTheme.inactiveTickMarkColor, equals(customColor1.withAlpha(0x8a)));
|
||||
expect(sliderTheme.disabledActiveTickMarkColor, equals(customColor3.withAlpha(0x1f)));
|
||||
@ -209,8 +219,10 @@ void main() {
|
||||
expect(lerp.trackHeight, equals(4.0));
|
||||
expect(lerp.activeTrackColor, equals(middleGrey.withAlpha(0xff)));
|
||||
expect(lerp.inactiveTrackColor, equals(middleGrey.withAlpha(0x3d)));
|
||||
expect(lerp.secondaryActiveTrackColor, equals(middleGrey.withAlpha(0x8a)));
|
||||
expect(lerp.disabledActiveTrackColor, equals(middleGrey.withAlpha(0x52)));
|
||||
expect(lerp.disabledInactiveTrackColor, equals(middleGrey.withAlpha(0x1f)));
|
||||
expect(lerp.disabledSecondaryActiveTrackColor, equals(middleGrey.withAlpha(0x1f)));
|
||||
expect(lerp.activeTickMarkColor, equals(middleGrey.withAlpha(0x8a)));
|
||||
expect(lerp.inactiveTickMarkColor, equals(middleGrey.withAlpha(0x8a)));
|
||||
expect(lerp.disabledActiveTickMarkColor, equals(middleGrey.withAlpha(0x1f)));
|
||||
@ -229,7 +241,7 @@ void main() {
|
||||
);
|
||||
final SliderThemeData sliderTheme = theme.sliderTheme.copyWith(thumbColor: Colors.red.shade500);
|
||||
|
||||
await tester.pumpWidget(_buildApp(sliderTheme, value: 0.25));
|
||||
await tester.pumpWidget(_buildApp(sliderTheme, value: 0.25, secondaryTrackValue: 0.5));
|
||||
final MaterialInkController material = Material.of(tester.element(find.byType(Slider)))!;
|
||||
|
||||
const Radius radius = Radius.circular(2);
|
||||
@ -241,10 +253,11 @@ void main() {
|
||||
material,
|
||||
paints
|
||||
..rrect(rrect: RRect.fromLTRBAndCorners(24.0, 297.0, 212.0, 303.0, topLeft: activatedRadius, bottomLeft: activatedRadius), color: sliderTheme.activeTrackColor)
|
||||
..rrect(rrect: RRect.fromLTRBAndCorners(212.0, 298.0, 776.0, 302.0, topRight: radius, bottomRight: radius), color: sliderTheme.inactiveTrackColor),
|
||||
..rrect(rrect: RRect.fromLTRBAndCorners(212.0, 298.0, 776.0, 302.0, topRight: radius, bottomRight: radius), color: sliderTheme.inactiveTrackColor)
|
||||
..rrect(rrect: RRect.fromLTRBAndCorners(212.0, 298.0, 400.0, 302.0, topRight: radius, bottomRight: radius), color: sliderTheme.secondaryActiveTrackColor),
|
||||
);
|
||||
|
||||
await tester.pumpWidget(_buildApp(sliderTheme, value: 0.25, enabled: false));
|
||||
await tester.pumpWidget(_buildApp(sliderTheme, value: 0.25, secondaryTrackValue: 0.5, enabled: false));
|
||||
await tester.pumpAndSettle(); // wait for disable animation
|
||||
|
||||
// The disabled slider thumb is the same size as the enabled thumb.
|
||||
@ -252,7 +265,8 @@ void main() {
|
||||
material,
|
||||
paints
|
||||
..rrect(rrect: RRect.fromLTRBAndCorners(24.0, 297.0, 212.0, 303.0, topLeft: activatedRadius, bottomLeft: activatedRadius), color: sliderTheme.disabledActiveTrackColor)
|
||||
..rrect(rrect: RRect.fromLTRBAndCorners(212.0, 298.0, 776.0, 302.0, topRight: radius, bottomRight: radius), color: sliderTheme.disabledInactiveTrackColor),
|
||||
..rrect(rrect: RRect.fromLTRBAndCorners(212.0, 298.0, 776.0, 302.0, topRight: radius, bottomRight: radius), color: sliderTheme.disabledInactiveTrackColor)
|
||||
..rrect(rrect: RRect.fromLTRBAndCorners(212.0, 298.0, 400.0, 302.0, topRight: radius, bottomRight: radius), color: sliderTheme.disabledSecondaryActiveTrackColor),
|
||||
);
|
||||
});
|
||||
|
||||
@ -1348,17 +1362,19 @@ class RoundedRectSliderTrackShapeWithCustomAdditionalActiveTrackHeight extends R
|
||||
required Animation<double> enableAnimation,
|
||||
required TextDirection textDirection,
|
||||
required Offset thumbCenter,
|
||||
Offset? secondaryOffset,
|
||||
bool isDiscrete = false,
|
||||
bool isEnabled = false,
|
||||
double additionalActiveTrackHeight = 2.0,
|
||||
}) {
|
||||
super.paint(context, offset, parentBox: parentBox, sliderTheme: sliderTheme, enableAnimation: enableAnimation, textDirection: textDirection, thumbCenter: thumbCenter, additionalActiveTrackHeight: this.additionalActiveTrackHeight);
|
||||
super.paint(context, offset, parentBox: parentBox, sliderTheme: sliderTheme, enableAnimation: enableAnimation, textDirection: textDirection, thumbCenter: thumbCenter, secondaryOffset: secondaryOffset, additionalActiveTrackHeight: this.additionalActiveTrackHeight);
|
||||
}
|
||||
}
|
||||
|
||||
Widget _buildApp(
|
||||
SliderThemeData sliderTheme, {
|
||||
double value = 0.0,
|
||||
double? secondaryTrackValue,
|
||||
bool enabled = true,
|
||||
int? divisions,
|
||||
}) {
|
||||
@ -1370,6 +1386,7 @@ Widget _buildApp(
|
||||
data: sliderTheme,
|
||||
child: Slider(
|
||||
value: value,
|
||||
secondaryTrackValue: secondaryTrackValue,
|
||||
label: '$value',
|
||||
onChanged: onChanged,
|
||||
divisions: divisions,
|
||||
|
Loading…
x
Reference in New Issue
Block a user