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 **
|
/// ** See code in examples/api/lib/material/slider/slider.0.dart **
|
||||||
/// {@end-tool}
|
/// {@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
|
/// 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
|
/// 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
|
/// [max]. To use discrete values, use a non-null value for [divisions], which
|
||||||
@ -125,6 +132,7 @@ class Slider extends StatefulWidget {
|
|||||||
const Slider({
|
const Slider({
|
||||||
super.key,
|
super.key,
|
||||||
required this.value,
|
required this.value,
|
||||||
|
this.secondaryTrackValue,
|
||||||
required this.onChanged,
|
required this.onChanged,
|
||||||
this.onChangeStart,
|
this.onChangeStart,
|
||||||
this.onChangeEnd,
|
this.onChangeEnd,
|
||||||
@ -134,6 +142,7 @@ class Slider extends StatefulWidget {
|
|||||||
this.label,
|
this.label,
|
||||||
this.activeColor,
|
this.activeColor,
|
||||||
this.inactiveColor,
|
this.inactiveColor,
|
||||||
|
this.secondaryActiveColor,
|
||||||
this.thumbColor,
|
this.thumbColor,
|
||||||
this.mouseCursor,
|
this.mouseCursor,
|
||||||
this.semanticFormatterCallback,
|
this.semanticFormatterCallback,
|
||||||
@ -146,6 +155,8 @@ class Slider extends StatefulWidget {
|
|||||||
assert(min <= max),
|
assert(min <= max),
|
||||||
assert(value >= min && value <= max,
|
assert(value >= min && value <= max,
|
||||||
'Value $value is not between minimum $min and maximum $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);
|
assert(divisions == null || divisions > 0);
|
||||||
|
|
||||||
/// Creates an adaptive [Slider] based on the target platform, following
|
/// 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
|
/// Creates a [CupertinoSlider] if the target platform is iOS or macOS, creates a
|
||||||
/// Material Design slider otherwise.
|
/// Material Design slider otherwise.
|
||||||
///
|
///
|
||||||
/// If a [CupertinoSlider] is created, the following parameters are
|
/// If a [CupertinoSlider] is created, the following parameters are ignored:
|
||||||
/// ignored: [label], [inactiveColor], [semanticFormatterCallback].
|
/// [secondaryTrackValue], [label], [inactiveColor], [secondaryActiveColor],
|
||||||
|
/// [semanticFormatterCallback].
|
||||||
///
|
///
|
||||||
/// The target platform is based on the current [Theme]: [ThemeData.platform].
|
/// The target platform is based on the current [Theme]: [ThemeData.platform].
|
||||||
const Slider.adaptive({
|
const Slider.adaptive({
|
||||||
super.key,
|
super.key,
|
||||||
required this.value,
|
required this.value,
|
||||||
|
this.secondaryTrackValue,
|
||||||
required this.onChanged,
|
required this.onChanged,
|
||||||
this.onChangeStart,
|
this.onChangeStart,
|
||||||
this.onChangeEnd,
|
this.onChangeEnd,
|
||||||
@ -172,6 +185,7 @@ class Slider extends StatefulWidget {
|
|||||||
this.mouseCursor,
|
this.mouseCursor,
|
||||||
this.activeColor,
|
this.activeColor,
|
||||||
this.inactiveColor,
|
this.inactiveColor,
|
||||||
|
this.secondaryActiveColor,
|
||||||
this.thumbColor,
|
this.thumbColor,
|
||||||
this.semanticFormatterCallback,
|
this.semanticFormatterCallback,
|
||||||
this.focusNode,
|
this.focusNode,
|
||||||
@ -181,7 +195,10 @@ class Slider extends StatefulWidget {
|
|||||||
assert(min != null),
|
assert(min != null),
|
||||||
assert(max != null),
|
assert(max != null),
|
||||||
assert(min <= max),
|
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);
|
assert(divisions == null || divisions > 0);
|
||||||
|
|
||||||
/// The currently selected value for this slider.
|
/// 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.
|
/// The slider's thumb is drawn at a position that corresponds to this value.
|
||||||
final double 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
|
/// Called during a drag when the user is selecting a new value for the slider
|
||||||
/// by dragging.
|
/// by dragging.
|
||||||
///
|
///
|
||||||
@ -365,6 +393,18 @@ class Slider extends StatefulWidget {
|
|||||||
/// Ignored if this slider is created with [Slider.adaptive].
|
/// Ignored if this slider is created with [Slider.adaptive].
|
||||||
final Color? inactiveColor;
|
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.
|
/// The color of the thumb.
|
||||||
///
|
///
|
||||||
/// If this color is null:
|
/// If this color is null:
|
||||||
@ -443,6 +483,7 @@ class Slider extends StatefulWidget {
|
|||||||
void debugFillProperties(DiagnosticPropertiesBuilder properties) {
|
void debugFillProperties(DiagnosticPropertiesBuilder properties) {
|
||||||
super.debugFillProperties(properties);
|
super.debugFillProperties(properties);
|
||||||
properties.add(DoubleProperty('value', value));
|
properties.add(DoubleProperty('value', value));
|
||||||
|
properties.add(DoubleProperty('secondaryTrackValue', secondaryTrackValue));
|
||||||
properties.add(ObjectFlagProperty<ValueChanged<double>>('onChanged', onChanged, ifNull: 'disabled'));
|
properties.add(ObjectFlagProperty<ValueChanged<double>>('onChanged', onChanged, ifNull: 'disabled'));
|
||||||
properties.add(ObjectFlagProperty<ValueChanged<double>>.has('onChangeStart', onChangeStart));
|
properties.add(ObjectFlagProperty<ValueChanged<double>>.has('onChangeStart', onChangeStart));
|
||||||
properties.add(ObjectFlagProperty<ValueChanged<double>>.has('onChangeEnd', onChangeEnd));
|
properties.add(ObjectFlagProperty<ValueChanged<double>>.has('onChangeEnd', onChangeEnd));
|
||||||
@ -452,6 +493,7 @@ class Slider extends StatefulWidget {
|
|||||||
properties.add(StringProperty('label', label));
|
properties.add(StringProperty('label', label));
|
||||||
properties.add(ColorProperty('activeColor', activeColor));
|
properties.add(ColorProperty('activeColor', activeColor));
|
||||||
properties.add(ColorProperty('inactiveColor', inactiveColor));
|
properties.add(ColorProperty('inactiveColor', inactiveColor));
|
||||||
|
properties.add(ColorProperty('secondaryActiveColor', secondaryActiveColor));
|
||||||
properties.add(ObjectFlagProperty<ValueChanged<double>>.has('semanticFormatterCallback', semanticFormatterCallback));
|
properties.add(ObjectFlagProperty<ValueChanged<double>>.has('semanticFormatterCallback', semanticFormatterCallback));
|
||||||
properties.add(ObjectFlagProperty<FocusNode>.has('focusNode', focusNode));
|
properties.add(ObjectFlagProperty<FocusNode>.has('focusNode', focusNode));
|
||||||
properties.add(FlagProperty('autofocus', value: autofocus, ifTrue: 'autofocus'));
|
properties.add(FlagProperty('autofocus', value: autofocus, ifTrue: 'autofocus'));
|
||||||
@ -708,8 +750,10 @@ class _SliderState extends State<Slider> with TickerProviderStateMixin {
|
|||||||
trackHeight: sliderTheme.trackHeight ?? defaultTrackHeight,
|
trackHeight: sliderTheme.trackHeight ?? defaultTrackHeight,
|
||||||
activeTrackColor: widget.activeColor ?? sliderTheme.activeTrackColor ?? theme.colorScheme.primary,
|
activeTrackColor: widget.activeColor ?? sliderTheme.activeTrackColor ?? theme.colorScheme.primary,
|
||||||
inactiveTrackColor: widget.inactiveColor ?? sliderTheme.inactiveTrackColor ?? theme.colorScheme.primary.withOpacity(0.24),
|
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),
|
disabledActiveTrackColor: sliderTheme.disabledActiveTrackColor ?? theme.colorScheme.onSurface.withOpacity(0.32),
|
||||||
disabledInactiveTrackColor: sliderTheme.disabledInactiveTrackColor ?? theme.colorScheme.onSurface.withOpacity(0.12),
|
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),
|
activeTickMarkColor: widget.inactiveColor ?? sliderTheme.activeTickMarkColor ?? theme.colorScheme.onPrimary.withOpacity(0.54),
|
||||||
inactiveTickMarkColor: widget.activeColor ?? sliderTheme.inactiveTickMarkColor ?? theme.colorScheme.primary.withOpacity(0.54),
|
inactiveTickMarkColor: widget.activeColor ?? sliderTheme.inactiveTickMarkColor ?? theme.colorScheme.primary.withOpacity(0.54),
|
||||||
disabledActiveTickMarkColor: sliderTheme.disabledActiveTickMarkColor ?? theme.colorScheme.onPrimary.withOpacity(0.12),
|
disabledActiveTickMarkColor: sliderTheme.disabledActiveTickMarkColor ?? theme.colorScheme.onPrimary.withOpacity(0.12),
|
||||||
@ -789,6 +833,7 @@ class _SliderState extends State<Slider> with TickerProviderStateMixin {
|
|||||||
child: _SliderRenderObjectWidget(
|
child: _SliderRenderObjectWidget(
|
||||||
key: _renderObjectKey,
|
key: _renderObjectKey,
|
||||||
value: _convert(widget.value),
|
value: _convert(widget.value),
|
||||||
|
secondaryTrackValue: (widget.secondaryTrackValue != null) ? _convert(widget.secondaryTrackValue!) : null,
|
||||||
divisions: widget.divisions,
|
divisions: widget.divisions,
|
||||||
label: widget.label,
|
label: widget.label,
|
||||||
sliderTheme: sliderTheme,
|
sliderTheme: sliderTheme,
|
||||||
@ -852,6 +897,7 @@ class _SliderRenderObjectWidget extends LeafRenderObjectWidget {
|
|||||||
const _SliderRenderObjectWidget({
|
const _SliderRenderObjectWidget({
|
||||||
super.key,
|
super.key,
|
||||||
required this.value,
|
required this.value,
|
||||||
|
required this.secondaryTrackValue,
|
||||||
required this.divisions,
|
required this.divisions,
|
||||||
required this.label,
|
required this.label,
|
||||||
required this.sliderTheme,
|
required this.sliderTheme,
|
||||||
@ -867,6 +913,7 @@ class _SliderRenderObjectWidget extends LeafRenderObjectWidget {
|
|||||||
});
|
});
|
||||||
|
|
||||||
final double value;
|
final double value;
|
||||||
|
final double? secondaryTrackValue;
|
||||||
final int? divisions;
|
final int? divisions;
|
||||||
final String? label;
|
final String? label;
|
||||||
final SliderThemeData sliderTheme;
|
final SliderThemeData sliderTheme;
|
||||||
@ -884,6 +931,7 @@ class _SliderRenderObjectWidget extends LeafRenderObjectWidget {
|
|||||||
_RenderSlider createRenderObject(BuildContext context) {
|
_RenderSlider createRenderObject(BuildContext context) {
|
||||||
return _RenderSlider(
|
return _RenderSlider(
|
||||||
value: value,
|
value: value,
|
||||||
|
secondaryTrackValue: secondaryTrackValue,
|
||||||
divisions: divisions,
|
divisions: divisions,
|
||||||
label: label,
|
label: label,
|
||||||
sliderTheme: sliderTheme,
|
sliderTheme: sliderTheme,
|
||||||
@ -909,6 +957,7 @@ class _SliderRenderObjectWidget extends LeafRenderObjectWidget {
|
|||||||
// setter dependent on the `divisions`.
|
// setter dependent on the `divisions`.
|
||||||
..divisions = divisions
|
..divisions = divisions
|
||||||
..value = value
|
..value = value
|
||||||
|
..secondaryTrackValue = secondaryTrackValue
|
||||||
..label = label
|
..label = label
|
||||||
..sliderTheme = sliderTheme
|
..sliderTheme = sliderTheme
|
||||||
..textScaleFactor = textScaleFactor
|
..textScaleFactor = textScaleFactor
|
||||||
@ -930,6 +979,7 @@ class _SliderRenderObjectWidget extends LeafRenderObjectWidget {
|
|||||||
class _RenderSlider extends RenderBox with RelayoutWhenSystemFontsChangeMixin {
|
class _RenderSlider extends RenderBox with RelayoutWhenSystemFontsChangeMixin {
|
||||||
_RenderSlider({
|
_RenderSlider({
|
||||||
required double value,
|
required double value,
|
||||||
|
required double? secondaryTrackValue,
|
||||||
required int? divisions,
|
required int? divisions,
|
||||||
required String? label,
|
required String? label,
|
||||||
required SliderThemeData sliderTheme,
|
required SliderThemeData sliderTheme,
|
||||||
@ -946,12 +996,14 @@ class _RenderSlider extends RenderBox with RelayoutWhenSystemFontsChangeMixin {
|
|||||||
required bool hovering,
|
required bool hovering,
|
||||||
required DeviceGestureSettings gestureSettings,
|
required DeviceGestureSettings gestureSettings,
|
||||||
}) : assert(value != null && value >= 0.0 && value <= 1.0),
|
}) : assert(value != null && value >= 0.0 && value <= 1.0),
|
||||||
|
assert(secondaryTrackValue == null || (secondaryTrackValue >= 0.0 && secondaryTrackValue <= 1.0)),
|
||||||
assert(state != null),
|
assert(state != null),
|
||||||
assert(textDirection != null),
|
assert(textDirection != null),
|
||||||
_platform = platform,
|
_platform = platform,
|
||||||
_semanticFormatterCallback = semanticFormatterCallback,
|
_semanticFormatterCallback = semanticFormatterCallback,
|
||||||
_label = label,
|
_label = label,
|
||||||
_value = value,
|
_value = value,
|
||||||
|
_secondaryTrackValue = secondaryTrackValue,
|
||||||
_divisions = divisions,
|
_divisions = divisions,
|
||||||
_sliderTheme = sliderTheme,
|
_sliderTheme = sliderTheme,
|
||||||
_textScaleFactor = textScaleFactor,
|
_textScaleFactor = textScaleFactor,
|
||||||
@ -1059,6 +1111,17 @@ class _RenderSlider extends RenderBox with RelayoutWhenSystemFontsChangeMixin {
|
|||||||
markNeedsSemanticsUpdate();
|
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;
|
DeviceGestureSettings? get gestureSettings => _drag.gestureSettings;
|
||||||
set gestureSettings(DeviceGestureSettings? gestureSettings) {
|
set gestureSettings(DeviceGestureSettings? gestureSettings) {
|
||||||
_drag.gestureSettings = gestureSettings;
|
_drag.gestureSettings = gestureSettings;
|
||||||
@ -1417,17 +1480,21 @@ class _RenderSlider extends RenderBox with RelayoutWhenSystemFontsChangeMixin {
|
|||||||
@override
|
@override
|
||||||
void paint(PaintingContext context, Offset offset) {
|
void paint(PaintingContext context, Offset offset) {
|
||||||
final double value = _state.positionController.value;
|
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
|
// 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
|
// to right. In left to right, this is the same as the value, but it is
|
||||||
// reversed for right to left text.
|
// reversed for right to left text.
|
||||||
final double visualPosition;
|
final double visualPosition;
|
||||||
|
final double? secondaryVisualPosition;
|
||||||
switch (textDirection) {
|
switch (textDirection) {
|
||||||
case TextDirection.rtl:
|
case TextDirection.rtl:
|
||||||
visualPosition = 1.0 - value;
|
visualPosition = 1.0 - value;
|
||||||
|
secondaryVisualPosition = (secondaryValue != null) ? (1.0 - secondaryValue) : null;
|
||||||
break;
|
break;
|
||||||
case TextDirection.ltr:
|
case TextDirection.ltr:
|
||||||
visualPosition = value;
|
visualPosition = value;
|
||||||
|
secondaryVisualPosition = (secondaryValue != null) ? secondaryValue : null;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1438,6 +1505,7 @@ class _RenderSlider extends RenderBox with RelayoutWhenSystemFontsChangeMixin {
|
|||||||
isDiscrete: isDiscrete,
|
isDiscrete: isDiscrete,
|
||||||
);
|
);
|
||||||
final Offset thumbCenter = Offset(trackRect.left + visualPosition * trackRect.width, trackRect.center.dy);
|
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(
|
_sliderTheme.trackShape!.paint(
|
||||||
context,
|
context,
|
||||||
@ -1447,6 +1515,7 @@ class _RenderSlider extends RenderBox with RelayoutWhenSystemFontsChangeMixin {
|
|||||||
enableAnimation: _enableAnimation,
|
enableAnimation: _enableAnimation,
|
||||||
textDirection: _textDirection,
|
textDirection: _textDirection,
|
||||||
thumbCenter: thumbCenter,
|
thumbCenter: thumbCenter,
|
||||||
|
secondaryOffset: secondaryOffset,
|
||||||
isDiscrete: isDiscrete,
|
isDiscrete: isDiscrete,
|
||||||
isEnabled: isInteractive,
|
isEnabled: isInteractive,
|
||||||
);
|
);
|
||||||
|
@ -266,8 +266,10 @@ class SliderThemeData with Diagnosticable {
|
|||||||
this.trackHeight,
|
this.trackHeight,
|
||||||
this.activeTrackColor,
|
this.activeTrackColor,
|
||||||
this.inactiveTrackColor,
|
this.inactiveTrackColor,
|
||||||
|
this.secondaryActiveTrackColor,
|
||||||
this.disabledActiveTrackColor,
|
this.disabledActiveTrackColor,
|
||||||
this.disabledInactiveTrackColor,
|
this.disabledInactiveTrackColor,
|
||||||
|
this.disabledSecondaryActiveTrackColor,
|
||||||
this.activeTickMarkColor,
|
this.activeTickMarkColor,
|
||||||
this.inactiveTickMarkColor,
|
this.inactiveTickMarkColor,
|
||||||
this.disabledActiveTickMarkColor,
|
this.disabledActiveTickMarkColor,
|
||||||
@ -317,8 +319,10 @@ class SliderThemeData with Diagnosticable {
|
|||||||
// component Colors (with opacity) from base colors.
|
// component Colors (with opacity) from base colors.
|
||||||
const int activeTrackAlpha = 0xff;
|
const int activeTrackAlpha = 0xff;
|
||||||
const int inactiveTrackAlpha = 0x3d; // 24% opacity
|
const int inactiveTrackAlpha = 0x3d; // 24% opacity
|
||||||
|
const int secondaryActiveTrackAlpha = 0x8a; // 54% opacity
|
||||||
const int disabledActiveTrackAlpha = 0x52; // 32% opacity
|
const int disabledActiveTrackAlpha = 0x52; // 32% opacity
|
||||||
const int disabledInactiveTrackAlpha = 0x1f; // 12% opacity
|
const int disabledInactiveTrackAlpha = 0x1f; // 12% opacity
|
||||||
|
const int disabledSecondaryActiveTrackAlpha = 0x1f; // 12% opacity
|
||||||
const int activeTickMarkAlpha = 0x8a; // 54% opacity
|
const int activeTickMarkAlpha = 0x8a; // 54% opacity
|
||||||
const int inactiveTickMarkAlpha = 0x8a; // 54% opacity
|
const int inactiveTickMarkAlpha = 0x8a; // 54% opacity
|
||||||
const int disabledActiveTickMarkAlpha = 0x1f; // 12% opacity
|
const int disabledActiveTickMarkAlpha = 0x1f; // 12% opacity
|
||||||
@ -332,8 +336,10 @@ class SliderThemeData with Diagnosticable {
|
|||||||
trackHeight: 2.0,
|
trackHeight: 2.0,
|
||||||
activeTrackColor: primaryColor.withAlpha(activeTrackAlpha),
|
activeTrackColor: primaryColor.withAlpha(activeTrackAlpha),
|
||||||
inactiveTrackColor: primaryColor.withAlpha(inactiveTrackAlpha),
|
inactiveTrackColor: primaryColor.withAlpha(inactiveTrackAlpha),
|
||||||
|
secondaryActiveTrackColor: primaryColor.withAlpha(secondaryActiveTrackAlpha),
|
||||||
disabledActiveTrackColor: primaryColorDark.withAlpha(disabledActiveTrackAlpha),
|
disabledActiveTrackColor: primaryColorDark.withAlpha(disabledActiveTrackAlpha),
|
||||||
disabledInactiveTrackColor: primaryColorDark.withAlpha(disabledInactiveTrackAlpha),
|
disabledInactiveTrackColor: primaryColorDark.withAlpha(disabledInactiveTrackAlpha),
|
||||||
|
disabledSecondaryActiveTrackColor: primaryColorDark.withAlpha(disabledSecondaryActiveTrackAlpha),
|
||||||
activeTickMarkColor: primaryColorLight.withAlpha(activeTickMarkAlpha),
|
activeTickMarkColor: primaryColorLight.withAlpha(activeTickMarkAlpha),
|
||||||
inactiveTickMarkColor: primaryColor.withAlpha(inactiveTickMarkAlpha),
|
inactiveTickMarkColor: primaryColor.withAlpha(inactiveTickMarkAlpha),
|
||||||
disabledActiveTickMarkColor: primaryColorLight.withAlpha(disabledActiveTickMarkAlpha),
|
disabledActiveTickMarkColor: primaryColorLight.withAlpha(disabledActiveTickMarkAlpha),
|
||||||
@ -368,10 +374,18 @@ class SliderThemeData with Diagnosticable {
|
|||||||
/// [Slider.max] position.
|
/// [Slider.max] position.
|
||||||
final Color? inactiveTrackColor;
|
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
|
/// The color of the [Slider] track between the [Slider.min] position and the
|
||||||
/// current thumb position when the [Slider] is disabled.
|
/// current thumb position when the [Slider] is disabled.
|
||||||
final Color? disabledActiveTrackColor;
|
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
|
/// The color of the [Slider] track between the current thumb position and the
|
||||||
/// [Slider.max] position when the [Slider] is disabled.
|
/// [Slider.max] position when the [Slider] is disabled.
|
||||||
final Color? disabledInactiveTrackColor;
|
final Color? disabledInactiveTrackColor;
|
||||||
@ -573,8 +587,10 @@ class SliderThemeData with Diagnosticable {
|
|||||||
double? trackHeight,
|
double? trackHeight,
|
||||||
Color? activeTrackColor,
|
Color? activeTrackColor,
|
||||||
Color? inactiveTrackColor,
|
Color? inactiveTrackColor,
|
||||||
|
Color? secondaryActiveTrackColor,
|
||||||
Color? disabledActiveTrackColor,
|
Color? disabledActiveTrackColor,
|
||||||
Color? disabledInactiveTrackColor,
|
Color? disabledInactiveTrackColor,
|
||||||
|
Color? disabledSecondaryActiveTrackColor,
|
||||||
Color? activeTickMarkColor,
|
Color? activeTickMarkColor,
|
||||||
Color? inactiveTickMarkColor,
|
Color? inactiveTickMarkColor,
|
||||||
Color? disabledActiveTickMarkColor,
|
Color? disabledActiveTickMarkColor,
|
||||||
@ -603,8 +619,10 @@ class SliderThemeData with Diagnosticable {
|
|||||||
trackHeight: trackHeight ?? this.trackHeight,
|
trackHeight: trackHeight ?? this.trackHeight,
|
||||||
activeTrackColor: activeTrackColor ?? this.activeTrackColor,
|
activeTrackColor: activeTrackColor ?? this.activeTrackColor,
|
||||||
inactiveTrackColor: inactiveTrackColor ?? this.inactiveTrackColor,
|
inactiveTrackColor: inactiveTrackColor ?? this.inactiveTrackColor,
|
||||||
|
secondaryActiveTrackColor: secondaryActiveTrackColor ?? this.secondaryActiveTrackColor,
|
||||||
disabledActiveTrackColor: disabledActiveTrackColor ?? this.disabledActiveTrackColor,
|
disabledActiveTrackColor: disabledActiveTrackColor ?? this.disabledActiveTrackColor,
|
||||||
disabledInactiveTrackColor: disabledInactiveTrackColor ?? this.disabledInactiveTrackColor,
|
disabledInactiveTrackColor: disabledInactiveTrackColor ?? this.disabledInactiveTrackColor,
|
||||||
|
disabledSecondaryActiveTrackColor: disabledSecondaryActiveTrackColor ?? this.disabledSecondaryActiveTrackColor,
|
||||||
activeTickMarkColor: activeTickMarkColor ?? this.activeTickMarkColor,
|
activeTickMarkColor: activeTickMarkColor ?? this.activeTickMarkColor,
|
||||||
inactiveTickMarkColor: inactiveTickMarkColor ?? this.inactiveTickMarkColor,
|
inactiveTickMarkColor: inactiveTickMarkColor ?? this.inactiveTickMarkColor,
|
||||||
disabledActiveTickMarkColor: disabledActiveTickMarkColor ?? this.disabledActiveTickMarkColor,
|
disabledActiveTickMarkColor: disabledActiveTickMarkColor ?? this.disabledActiveTickMarkColor,
|
||||||
@ -644,8 +662,10 @@ class SliderThemeData with Diagnosticable {
|
|||||||
trackHeight: lerpDouble(a.trackHeight, b.trackHeight, t),
|
trackHeight: lerpDouble(a.trackHeight, b.trackHeight, t),
|
||||||
activeTrackColor: Color.lerp(a.activeTrackColor, b.activeTrackColor, t),
|
activeTrackColor: Color.lerp(a.activeTrackColor, b.activeTrackColor, t),
|
||||||
inactiveTrackColor: Color.lerp(a.inactiveTrackColor, b.inactiveTrackColor, 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),
|
disabledActiveTrackColor: Color.lerp(a.disabledActiveTrackColor, b.disabledActiveTrackColor, t),
|
||||||
disabledInactiveTrackColor: Color.lerp(a.disabledInactiveTrackColor, b.disabledInactiveTrackColor, 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),
|
activeTickMarkColor: Color.lerp(a.activeTickMarkColor, b.activeTickMarkColor, t),
|
||||||
inactiveTickMarkColor: Color.lerp(a.inactiveTickMarkColor, b.inactiveTickMarkColor, t),
|
inactiveTickMarkColor: Color.lerp(a.inactiveTickMarkColor, b.inactiveTickMarkColor, t),
|
||||||
disabledActiveTickMarkColor: Color.lerp(a.disabledActiveTickMarkColor, b.disabledActiveTickMarkColor, t),
|
disabledActiveTickMarkColor: Color.lerp(a.disabledActiveTickMarkColor, b.disabledActiveTickMarkColor, t),
|
||||||
@ -677,8 +697,10 @@ class SliderThemeData with Diagnosticable {
|
|||||||
trackHeight,
|
trackHeight,
|
||||||
activeTrackColor,
|
activeTrackColor,
|
||||||
inactiveTrackColor,
|
inactiveTrackColor,
|
||||||
|
secondaryActiveTrackColor,
|
||||||
disabledActiveTrackColor,
|
disabledActiveTrackColor,
|
||||||
disabledInactiveTrackColor,
|
disabledInactiveTrackColor,
|
||||||
|
disabledSecondaryActiveTrackColor,
|
||||||
activeTickMarkColor,
|
activeTickMarkColor,
|
||||||
inactiveTickMarkColor,
|
inactiveTickMarkColor,
|
||||||
disabledActiveTickMarkColor,
|
disabledActiveTickMarkColor,
|
||||||
@ -691,9 +713,9 @@ class SliderThemeData with Diagnosticable {
|
|||||||
overlayShape,
|
overlayShape,
|
||||||
tickMarkShape,
|
tickMarkShape,
|
||||||
thumbShape,
|
thumbShape,
|
||||||
trackShape,
|
|
||||||
valueIndicatorShape,
|
|
||||||
Object.hash(
|
Object.hash(
|
||||||
|
trackShape,
|
||||||
|
valueIndicatorShape,
|
||||||
rangeTickMarkShape,
|
rangeTickMarkShape,
|
||||||
rangeThumbShape,
|
rangeThumbShape,
|
||||||
rangeTrackShape,
|
rangeTrackShape,
|
||||||
@ -718,8 +740,10 @@ class SliderThemeData with Diagnosticable {
|
|||||||
&& other.trackHeight == trackHeight
|
&& other.trackHeight == trackHeight
|
||||||
&& other.activeTrackColor == activeTrackColor
|
&& other.activeTrackColor == activeTrackColor
|
||||||
&& other.inactiveTrackColor == inactiveTrackColor
|
&& other.inactiveTrackColor == inactiveTrackColor
|
||||||
|
&& other.secondaryActiveTrackColor == secondaryActiveTrackColor
|
||||||
&& other.disabledActiveTrackColor == disabledActiveTrackColor
|
&& other.disabledActiveTrackColor == disabledActiveTrackColor
|
||||||
&& other.disabledInactiveTrackColor == disabledInactiveTrackColor
|
&& other.disabledInactiveTrackColor == disabledInactiveTrackColor
|
||||||
|
&& other.disabledSecondaryActiveTrackColor == disabledSecondaryActiveTrackColor
|
||||||
&& other.activeTickMarkColor == activeTickMarkColor
|
&& other.activeTickMarkColor == activeTickMarkColor
|
||||||
&& other.inactiveTickMarkColor == inactiveTickMarkColor
|
&& other.inactiveTickMarkColor == inactiveTickMarkColor
|
||||||
&& other.disabledActiveTickMarkColor == disabledActiveTickMarkColor
|
&& other.disabledActiveTickMarkColor == disabledActiveTickMarkColor
|
||||||
@ -752,8 +776,10 @@ class SliderThemeData with Diagnosticable {
|
|||||||
properties.add(DoubleProperty('trackHeight', trackHeight, defaultValue: defaultData.trackHeight));
|
properties.add(DoubleProperty('trackHeight', trackHeight, defaultValue: defaultData.trackHeight));
|
||||||
properties.add(ColorProperty('activeTrackColor', activeTrackColor, defaultValue: defaultData.activeTrackColor));
|
properties.add(ColorProperty('activeTrackColor', activeTrackColor, defaultValue: defaultData.activeTrackColor));
|
||||||
properties.add(ColorProperty('inactiveTrackColor', inactiveTrackColor, defaultValue: defaultData.inactiveTrackColor));
|
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('disabledActiveTrackColor', disabledActiveTrackColor, defaultValue: defaultData.disabledActiveTrackColor));
|
||||||
properties.add(ColorProperty('disabledInactiveTrackColor', disabledInactiveTrackColor, defaultValue: defaultData.disabledInactiveTrackColor));
|
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('activeTickMarkColor', activeTickMarkColor, defaultValue: defaultData.activeTickMarkColor));
|
||||||
properties.add(ColorProperty('inactiveTickMarkColor', inactiveTickMarkColor, defaultValue: defaultData.inactiveTickMarkColor));
|
properties.add(ColorProperty('inactiveTickMarkColor', inactiveTickMarkColor, defaultValue: defaultData.inactiveTickMarkColor));
|
||||||
properties.add(ColorProperty('disabledActiveTickMarkColor', disabledActiveTickMarkColor, defaultValue: defaultData.disabledActiveTickMarkColor));
|
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
|
/// relative to the origin of the [PaintingContext.canvas]. It can be used as
|
||||||
/// the point that divides the track into 2 segments.
|
/// 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.SliderTickMarkShape.getPreferredSize.isEnabled}
|
||||||
///
|
///
|
||||||
/// {@macro flutter.material.SliderComponentShape.paint.isDiscrete}
|
/// {@macro flutter.material.SliderComponentShape.paint.isDiscrete}
|
||||||
@ -1068,6 +1099,7 @@ abstract class SliderTrackShape {
|
|||||||
required SliderThemeData sliderTheme,
|
required SliderThemeData sliderTheme,
|
||||||
required Animation<double> enableAnimation,
|
required Animation<double> enableAnimation,
|
||||||
required Offset thumbCenter,
|
required Offset thumbCenter,
|
||||||
|
Offset? secondaryOffset,
|
||||||
bool isEnabled,
|
bool isEnabled,
|
||||||
bool isDiscrete,
|
bool isDiscrete,
|
||||||
required TextDirection textDirection,
|
required TextDirection textDirection,
|
||||||
@ -1534,6 +1566,7 @@ class RectangularSliderTrackShape extends SliderTrackShape with BaseSliderTrackS
|
|||||||
required Animation<double> enableAnimation,
|
required Animation<double> enableAnimation,
|
||||||
required TextDirection textDirection,
|
required TextDirection textDirection,
|
||||||
required Offset thumbCenter,
|
required Offset thumbCenter,
|
||||||
|
Offset? secondaryOffset,
|
||||||
bool isDiscrete = false,
|
bool isDiscrete = false,
|
||||||
bool isEnabled = false,
|
bool isEnabled = false,
|
||||||
}) {
|
}) {
|
||||||
@ -1593,6 +1626,25 @@ class RectangularSliderTrackShape extends SliderTrackShape with BaseSliderTrackS
|
|||||||
if (!rightTrackSegment.isEmpty) {
|
if (!rightTrackSegment.isEmpty) {
|
||||||
context.canvas.drawRect(rightTrackSegment, rightTrackPaint);
|
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 Animation<double> enableAnimation,
|
||||||
required TextDirection textDirection,
|
required TextDirection textDirection,
|
||||||
required Offset thumbCenter,
|
required Offset thumbCenter,
|
||||||
|
Offset? secondaryOffset,
|
||||||
bool isDiscrete = false,
|
bool isDiscrete = false,
|
||||||
bool isEnabled = false,
|
bool isEnabled = false,
|
||||||
double additionalActiveTrackHeight = 2,
|
double additionalActiveTrackHeight = 2,
|
||||||
@ -1709,6 +1762,41 @@ class RoundedRectSliderTrackShape extends SliderTrackShape with BaseSliderTrackS
|
|||||||
),
|
),
|
||||||
rightTrackPaint,
|
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 {
|
try {
|
||||||
const Color customColor1 = Color(0xcafefeed);
|
const Color customColor1 = Color(0xcafefeed);
|
||||||
const Color customColor2 = Color(0xdeadbeef);
|
const Color customColor2 = Color(0xdeadbeef);
|
||||||
|
const Color customColor3 = Color(0xdecaface);
|
||||||
final ThemeData theme = ThemeData(
|
final ThemeData theme = ThemeData(
|
||||||
platform: TargetPlatform.android,
|
platform: TargetPlatform.android,
|
||||||
primarySwatch: Colors.blue,
|
primarySwatch: Colors.blue,
|
||||||
@ -647,6 +648,8 @@ void main() {
|
|||||||
overlayColor: Color(0xff000010),
|
overlayColor: Color(0xff000010),
|
||||||
thumbColor: Color(0xff000011),
|
thumbColor: Color(0xff000011),
|
||||||
valueIndicatorColor: Color(0xff000012),
|
valueIndicatorColor: Color(0xff000012),
|
||||||
|
disabledSecondaryActiveTrackColor: Color(0xff000013),
|
||||||
|
secondaryActiveTrackColor: Color(0xff000014),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
final SliderThemeData sliderTheme = theme.sliderTheme;
|
final SliderThemeData sliderTheme = theme.sliderTheme;
|
||||||
@ -654,6 +657,7 @@ void main() {
|
|||||||
Widget buildApp({
|
Widget buildApp({
|
||||||
Color? activeColor,
|
Color? activeColor,
|
||||||
Color? inactiveColor,
|
Color? inactiveColor,
|
||||||
|
Color? secondaryActiveColor,
|
||||||
int? divisions,
|
int? divisions,
|
||||||
bool enabled = true,
|
bool enabled = true,
|
||||||
}) {
|
}) {
|
||||||
@ -671,10 +675,12 @@ void main() {
|
|||||||
data: theme,
|
data: theme,
|
||||||
child: Slider(
|
child: Slider(
|
||||||
value: value,
|
value: value,
|
||||||
|
secondaryTrackValue: 0.75,
|
||||||
label: '$value',
|
label: '$value',
|
||||||
divisions: divisions,
|
divisions: divisions,
|
||||||
activeColor: activeColor,
|
activeColor: activeColor,
|
||||||
inactiveColor: inactiveColor,
|
inactiveColor: inactiveColor,
|
||||||
|
secondaryActiveColor: secondaryActiveColor,
|
||||||
onChanged: onChanged,
|
onChanged: onChanged,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@ -690,47 +696,61 @@ void main() {
|
|||||||
final RenderBox valueIndicatorBox = tester.renderObject(find.byType(Overlay));
|
final RenderBox valueIndicatorBox = tester.renderObject(find.byType(Overlay));
|
||||||
|
|
||||||
// Check default theme for enabled widget.
|
// 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..shadow(color: const Color(0xff000000)));
|
||||||
expect(material, paints..circle(color: sliderTheme.thumbColor));
|
expect(material, paints..circle(color: sliderTheme.thumbColor));
|
||||||
expect(material, isNot(paints..circle(color: sliderTheme.disabledThumbColor)));
|
expect(material, isNot(paints..circle(color: sliderTheme.disabledThumbColor)));
|
||||||
expect(material, isNot(paints..rrect(color: sliderTheme.disabledActiveTrackColor)));
|
expect(material, isNot(paints..rrect(color: sliderTheme.disabledActiveTrackColor)));
|
||||||
expect(material, isNot(paints..rrect(color: sliderTheme.disabledInactiveTrackColor)));
|
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.activeTickMarkColor)));
|
||||||
expect(material, isNot(paints..circle(color: sliderTheme.inactiveTickMarkColor)));
|
expect(material, isNot(paints..circle(color: sliderTheme.inactiveTickMarkColor)));
|
||||||
|
|
||||||
// Test setting only the activeColor.
|
// Test setting only the activeColor.
|
||||||
await tester.pumpWidget(buildApp(activeColor: customColor1));
|
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..shadow(color: Colors.black));
|
||||||
expect(material, paints..circle(color: customColor1));
|
expect(material, paints..circle(color: customColor1));
|
||||||
expect(material, isNot(paints..circle(color: sliderTheme.thumbColor)));
|
expect(material, isNot(paints..circle(color: sliderTheme.thumbColor)));
|
||||||
expect(material, isNot(paints..circle(color: sliderTheme.disabledThumbColor)));
|
expect(material, isNot(paints..circle(color: sliderTheme.disabledThumbColor)));
|
||||||
expect(material, isNot(paints..rrect(color: sliderTheme.disabledActiveTrackColor)));
|
expect(material, isNot(paints..rrect(color: sliderTheme.disabledActiveTrackColor)));
|
||||||
expect(material, isNot(paints..rrect(color: sliderTheme.disabledInactiveTrackColor)));
|
expect(material, isNot(paints..rrect(color: sliderTheme.disabledInactiveTrackColor)));
|
||||||
|
expect(material, isNot(paints..rrect(color: sliderTheme.disabledSecondaryActiveTrackColor)));
|
||||||
|
|
||||||
// Test setting only the inactiveColor.
|
// Test setting only the inactiveColor.
|
||||||
await tester.pumpWidget(buildApp(inactiveColor: customColor1));
|
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..shadow(color: Colors.black));
|
||||||
expect(material, paints..circle(color: sliderTheme.thumbColor));
|
expect(material, paints..circle(color: sliderTheme.thumbColor));
|
||||||
expect(material, isNot(paints..circle(color: sliderTheme.disabledThumbColor)));
|
expect(material, isNot(paints..circle(color: sliderTheme.disabledThumbColor)));
|
||||||
expect(material, isNot(paints..rrect(color: sliderTheme.disabledActiveTrackColor)));
|
expect(material, isNot(paints..rrect(color: sliderTheme.disabledActiveTrackColor)));
|
||||||
expect(material, isNot(paints..rrect(color: sliderTheme.disabledInactiveTrackColor)));
|
expect(material, isNot(paints..rrect(color: sliderTheme.disabledInactiveTrackColor)));
|
||||||
|
expect(material, isNot(paints..rrect(color: sliderTheme.disabledSecondaryActiveTrackColor)));
|
||||||
|
|
||||||
// Test setting both activeColor and inactiveColor.
|
// Test setting only the secondaryActiveColor.
|
||||||
await tester.pumpWidget(buildApp(activeColor: customColor1, inactiveColor: customColor2));
|
await tester.pumpWidget(buildApp(secondaryActiveColor: customColor1));
|
||||||
expect(material, paints..rrect(color: customColor1)..rrect(color: customColor2));
|
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..shadow(color: Colors.black));
|
||||||
expect(material, paints..circle(color: customColor1));
|
expect(material, paints..circle(color: customColor1));
|
||||||
expect(material, isNot(paints..circle(color: sliderTheme.thumbColor)));
|
expect(material, isNot(paints..circle(color: sliderTheme.thumbColor)));
|
||||||
expect(material, isNot(paints..circle(color: sliderTheme.disabledThumbColor)));
|
expect(material, isNot(paints..circle(color: sliderTheme.disabledThumbColor)));
|
||||||
expect(material, isNot(paints..rrect(color: sliderTheme.disabledActiveTrackColor)));
|
expect(material, isNot(paints..rrect(color: sliderTheme.disabledActiveTrackColor)));
|
||||||
expect(material, isNot(paints..rrect(color: sliderTheme.disabledInactiveTrackColor)));
|
expect(material, isNot(paints..rrect(color: sliderTheme.disabledInactiveTrackColor)));
|
||||||
|
expect(material, isNot(paints..rrect(color: sliderTheme.disabledSecondaryActiveTrackColor)));
|
||||||
|
|
||||||
// Test colors for discrete slider.
|
// Test colors for discrete slider.
|
||||||
await tester.pumpWidget(buildApp(divisions: 3));
|
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(
|
expect(
|
||||||
material,
|
material,
|
||||||
paints
|
paints
|
||||||
@ -744,14 +764,16 @@ void main() {
|
|||||||
expect(material, isNot(paints..circle(color: sliderTheme.disabledThumbColor)));
|
expect(material, isNot(paints..circle(color: sliderTheme.disabledThumbColor)));
|
||||||
expect(material, isNot(paints..rrect(color: sliderTheme.disabledActiveTrackColor)));
|
expect(material, isNot(paints..rrect(color: sliderTheme.disabledActiveTrackColor)));
|
||||||
expect(material, isNot(paints..rrect(color: sliderTheme.disabledInactiveTrackColor)));
|
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.
|
// Test colors for discrete slider with inactiveColor and activeColor set.
|
||||||
await tester.pumpWidget(buildApp(
|
await tester.pumpWidget(buildApp(
|
||||||
activeColor: customColor1,
|
activeColor: customColor1,
|
||||||
inactiveColor: customColor2,
|
inactiveColor: customColor2,
|
||||||
|
secondaryActiveColor: customColor3,
|
||||||
divisions: 3,
|
divisions: 3,
|
||||||
));
|
));
|
||||||
expect(material, paints..rrect(color: customColor1)..rrect(color: customColor2));
|
expect(material, paints..rrect(color: customColor1)..rrect(color: customColor2)..rrect(color: customColor3));
|
||||||
expect(
|
expect(
|
||||||
material,
|
material,
|
||||||
paints
|
paints
|
||||||
@ -766,6 +788,7 @@ void main() {
|
|||||||
expect(material, isNot(paints..circle(color: sliderTheme.disabledThumbColor)));
|
expect(material, isNot(paints..circle(color: sliderTheme.disabledThumbColor)));
|
||||||
expect(material, isNot(paints..rrect(color: sliderTheme.disabledActiveTrackColor)));
|
expect(material, isNot(paints..rrect(color: sliderTheme.disabledActiveTrackColor)));
|
||||||
expect(material, isNot(paints..rrect(color: sliderTheme.disabledInactiveTrackColor)));
|
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.activeTickMarkColor)));
|
||||||
expect(material, isNot(paints..circle(color: sliderTheme.inactiveTickMarkColor)));
|
expect(material, isNot(paints..circle(color: sliderTheme.inactiveTickMarkColor)));
|
||||||
|
|
||||||
@ -776,25 +799,29 @@ void main() {
|
|||||||
material,
|
material,
|
||||||
paints
|
paints
|
||||||
..rrect(color: sliderTheme.disabledActiveTrackColor)
|
..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, paints..shadow(color: Colors.black)..circle(color: sliderTheme.disabledThumbColor));
|
||||||
expect(material, isNot(paints..circle(color: sliderTheme.thumbColor)));
|
expect(material, isNot(paints..circle(color: sliderTheme.thumbColor)));
|
||||||
expect(material, isNot(paints..rrect(color: sliderTheme.activeTrackColor)));
|
expect(material, isNot(paints..rrect(color: sliderTheme.activeTrackColor)));
|
||||||
expect(material, isNot(paints..rrect(color: sliderTheme.inactiveTrackColor)));
|
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.
|
// Test setting the activeColor, inactiveColor and secondaryActiveColor for disabled widget.
|
||||||
await tester.pumpWidget(buildApp(activeColor: customColor1, inactiveColor: customColor2, enabled: false));
|
await tester.pumpWidget(buildApp(activeColor: customColor1, inactiveColor: customColor2, secondaryActiveColor: customColor3, enabled: false));
|
||||||
expect(
|
expect(
|
||||||
material,
|
material,
|
||||||
paints
|
paints
|
||||||
..rrect(color: sliderTheme.disabledActiveTrackColor)
|
..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, paints..circle(color: sliderTheme.disabledThumbColor));
|
||||||
expect(material, isNot(paints..circle(color: sliderTheme.thumbColor)));
|
expect(material, isNot(paints..circle(color: sliderTheme.thumbColor)));
|
||||||
expect(material, isNot(paints..rrect(color: sliderTheme.activeTrackColor)));
|
expect(material, isNot(paints..rrect(color: sliderTheme.activeTrackColor)));
|
||||||
expect(material, isNot(paints..rrect(color: sliderTheme.inactiveTrackColor)));
|
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.
|
// Test that the default value indicator has the right colors.
|
||||||
await tester.pumpWidget(buildApp(divisions: 3));
|
await tester.pumpWidget(buildApp(divisions: 3));
|
||||||
@ -2813,10 +2840,12 @@ void main() {
|
|||||||
activeColor: Colors.blue,
|
activeColor: Colors.blue,
|
||||||
divisions: 10,
|
divisions: 10,
|
||||||
inactiveColor: Colors.grey,
|
inactiveColor: Colors.grey,
|
||||||
|
secondaryActiveColor: Colors.blueGrey,
|
||||||
label: 'Set a value',
|
label: 'Set a value',
|
||||||
max: 100.0,
|
max: 100.0,
|
||||||
onChanged: null,
|
onChanged: null,
|
||||||
value: 50.0,
|
value: 50.0,
|
||||||
|
secondaryTrackValue: 75.0,
|
||||||
).debugFillProperties(builder);
|
).debugFillProperties(builder);
|
||||||
|
|
||||||
final List<String> description = builder.properties
|
final List<String> description = builder.properties
|
||||||
@ -2825,6 +2854,7 @@ void main() {
|
|||||||
|
|
||||||
expect(description, <String>[
|
expect(description, <String>[
|
||||||
'value: 50.0',
|
'value: 50.0',
|
||||||
|
'secondaryTrackValue: 75.0',
|
||||||
'disabled',
|
'disabled',
|
||||||
'min: 0.0',
|
'min: 0.0',
|
||||||
'max: 100.0',
|
'max: 100.0',
|
||||||
@ -2832,6 +2862,7 @@ void main() {
|
|||||||
'label: "Set a value"',
|
'label: "Set a value"',
|
||||||
'activeColor: MaterialColor(primary value: Color(0xff2196f3))',
|
'activeColor: MaterialColor(primary value: Color(0xff2196f3))',
|
||||||
'inactiveColor: MaterialColor(primary value: Color(0xff9e9e9e))',
|
'inactiveColor: MaterialColor(primary value: Color(0xff9e9e9e))',
|
||||||
|
'secondaryActiveColor: MaterialColor(primary value: Color(0xff607d8b))',
|
||||||
]);
|
]);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -34,17 +34,19 @@ void main() {
|
|||||||
trackHeight: 7.0,
|
trackHeight: 7.0,
|
||||||
activeTrackColor: Color(0xFF000001),
|
activeTrackColor: Color(0xFF000001),
|
||||||
inactiveTrackColor: Color(0xFF000002),
|
inactiveTrackColor: Color(0xFF000002),
|
||||||
disabledActiveTrackColor: Color(0xFF000003),
|
secondaryActiveTrackColor: Color(0xFF000003),
|
||||||
disabledInactiveTrackColor: Color(0xFF000004),
|
disabledActiveTrackColor: Color(0xFF000004),
|
||||||
activeTickMarkColor: Color(0xFF000005),
|
disabledInactiveTrackColor: Color(0xFF000005),
|
||||||
inactiveTickMarkColor: Color(0xFF000006),
|
disabledSecondaryActiveTrackColor: Color(0xFF000006),
|
||||||
disabledActiveTickMarkColor: Color(0xFF000007),
|
activeTickMarkColor: Color(0xFF000007),
|
||||||
disabledInactiveTickMarkColor: Color(0xFF000008),
|
inactiveTickMarkColor: Color(0xFF000008),
|
||||||
thumbColor: Color(0xFF000009),
|
disabledActiveTickMarkColor: Color(0xFF000009),
|
||||||
overlappingShapeStrokeColor: Color(0xFF000010),
|
disabledInactiveTickMarkColor: Color(0xFF000010),
|
||||||
disabledThumbColor: Color(0xFF000011),
|
thumbColor: Color(0xFF000011),
|
||||||
overlayColor: Color(0xFF000012),
|
overlappingShapeStrokeColor: Color(0xFF000012),
|
||||||
valueIndicatorColor: Color(0xFF000013),
|
disabledThumbColor: Color(0xFF000013),
|
||||||
|
overlayColor: Color(0xFF000014),
|
||||||
|
valueIndicatorColor: Color(0xFF000015),
|
||||||
overlayShape: RoundSliderOverlayShape(),
|
overlayShape: RoundSliderOverlayShape(),
|
||||||
tickMarkShape: RoundSliderTickMarkShape(),
|
tickMarkShape: RoundSliderTickMarkShape(),
|
||||||
thumbShape: RoundSliderThumbShape(),
|
thumbShape: RoundSliderThumbShape(),
|
||||||
@ -68,17 +70,19 @@ void main() {
|
|||||||
'trackHeight: 7.0',
|
'trackHeight: 7.0',
|
||||||
'activeTrackColor: Color(0xff000001)',
|
'activeTrackColor: Color(0xff000001)',
|
||||||
'inactiveTrackColor: Color(0xff000002)',
|
'inactiveTrackColor: Color(0xff000002)',
|
||||||
'disabledActiveTrackColor: Color(0xff000003)',
|
'secondaryActiveTrackColor: Color(0xff000003)',
|
||||||
'disabledInactiveTrackColor: Color(0xff000004)',
|
'disabledActiveTrackColor: Color(0xff000004)',
|
||||||
'activeTickMarkColor: Color(0xff000005)',
|
'disabledInactiveTrackColor: Color(0xff000005)',
|
||||||
'inactiveTickMarkColor: Color(0xff000006)',
|
'disabledSecondaryActiveTrackColor: Color(0xff000006)',
|
||||||
'disabledActiveTickMarkColor: Color(0xff000007)',
|
'activeTickMarkColor: Color(0xff000007)',
|
||||||
'disabledInactiveTickMarkColor: Color(0xff000008)',
|
'inactiveTickMarkColor: Color(0xff000008)',
|
||||||
'thumbColor: Color(0xff000009)',
|
'disabledActiveTickMarkColor: Color(0xff000009)',
|
||||||
'overlappingShapeStrokeColor: Color(0xff000010)',
|
'disabledInactiveTickMarkColor: Color(0xff000010)',
|
||||||
'disabledThumbColor: Color(0xff000011)',
|
'thumbColor: Color(0xff000011)',
|
||||||
'overlayColor: Color(0xff000012)',
|
'overlappingShapeStrokeColor: Color(0xff000012)',
|
||||||
'valueIndicatorColor: Color(0xff000013)',
|
'disabledThumbColor: Color(0xff000013)',
|
||||||
|
'overlayColor: Color(0xff000014)',
|
||||||
|
'valueIndicatorColor: Color(0xff000015)',
|
||||||
"overlayShape: Instance of 'RoundSliderOverlayShape'",
|
"overlayShape: Instance of 'RoundSliderOverlayShape'",
|
||||||
"tickMarkShape: Instance of 'RoundSliderTickMarkShape'",
|
"tickMarkShape: Instance of 'RoundSliderTickMarkShape'",
|
||||||
"thumbShape: Instance of 'RoundSliderThumbShape'",
|
"thumbShape: Instance of 'RoundSliderThumbShape'",
|
||||||
@ -103,16 +107,18 @@ void main() {
|
|||||||
final SliderThemeData customTheme = sliderTheme.copyWith(
|
final SliderThemeData customTheme = sliderTheme.copyWith(
|
||||||
activeTrackColor: Colors.purple,
|
activeTrackColor: Colors.purple,
|
||||||
inactiveTrackColor: Colors.purple.withAlpha(0x3d),
|
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)))!;
|
final MaterialInkController material = Material.of(tester.element(find.byType(Slider)))!;
|
||||||
|
|
||||||
expect(
|
expect(
|
||||||
material,
|
material,
|
||||||
paints
|
paints
|
||||||
..rrect(color: customTheme.disabledActiveTrackColor)
|
..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(
|
final SliderThemeData customTheme = sliderTheme.copyWith(
|
||||||
activeTrackColor: Colors.purple,
|
activeTrackColor: Colors.purple,
|
||||||
inactiveTrackColor: Colors.purple.withAlpha(0x3d),
|
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)))!;
|
final MaterialInkController material = Material.of(tester.element(find.byType(Slider)))!;
|
||||||
|
|
||||||
expect(
|
expect(
|
||||||
material,
|
material,
|
||||||
paints
|
paints
|
||||||
..rrect(color: customTheme.disabledActiveTrackColor)
|
..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.activeTrackColor, equals(customColor1.withAlpha(0xff)));
|
||||||
expect(sliderTheme.inactiveTrackColor, equals(customColor1.withAlpha(0x3d)));
|
expect(sliderTheme.inactiveTrackColor, equals(customColor1.withAlpha(0x3d)));
|
||||||
|
expect(sliderTheme.secondaryActiveTrackColor, equals(customColor1.withAlpha(0x8a)));
|
||||||
expect(sliderTheme.disabledActiveTrackColor, equals(customColor2.withAlpha(0x52)));
|
expect(sliderTheme.disabledActiveTrackColor, equals(customColor2.withAlpha(0x52)));
|
||||||
expect(sliderTheme.disabledInactiveTrackColor, equals(customColor2.withAlpha(0x1f)));
|
expect(sliderTheme.disabledInactiveTrackColor, equals(customColor2.withAlpha(0x1f)));
|
||||||
|
expect(sliderTheme.disabledSecondaryActiveTrackColor, equals(customColor2.withAlpha(0x1f)));
|
||||||
expect(sliderTheme.activeTickMarkColor, equals(customColor3.withAlpha(0x8a)));
|
expect(sliderTheme.activeTickMarkColor, equals(customColor3.withAlpha(0x8a)));
|
||||||
expect(sliderTheme.inactiveTickMarkColor, equals(customColor1.withAlpha(0x8a)));
|
expect(sliderTheme.inactiveTickMarkColor, equals(customColor1.withAlpha(0x8a)));
|
||||||
expect(sliderTheme.disabledActiveTickMarkColor, equals(customColor3.withAlpha(0x1f)));
|
expect(sliderTheme.disabledActiveTickMarkColor, equals(customColor3.withAlpha(0x1f)));
|
||||||
@ -209,8 +219,10 @@ void main() {
|
|||||||
expect(lerp.trackHeight, equals(4.0));
|
expect(lerp.trackHeight, equals(4.0));
|
||||||
expect(lerp.activeTrackColor, equals(middleGrey.withAlpha(0xff)));
|
expect(lerp.activeTrackColor, equals(middleGrey.withAlpha(0xff)));
|
||||||
expect(lerp.inactiveTrackColor, equals(middleGrey.withAlpha(0x3d)));
|
expect(lerp.inactiveTrackColor, equals(middleGrey.withAlpha(0x3d)));
|
||||||
|
expect(lerp.secondaryActiveTrackColor, equals(middleGrey.withAlpha(0x8a)));
|
||||||
expect(lerp.disabledActiveTrackColor, equals(middleGrey.withAlpha(0x52)));
|
expect(lerp.disabledActiveTrackColor, equals(middleGrey.withAlpha(0x52)));
|
||||||
expect(lerp.disabledInactiveTrackColor, equals(middleGrey.withAlpha(0x1f)));
|
expect(lerp.disabledInactiveTrackColor, equals(middleGrey.withAlpha(0x1f)));
|
||||||
|
expect(lerp.disabledSecondaryActiveTrackColor, equals(middleGrey.withAlpha(0x1f)));
|
||||||
expect(lerp.activeTickMarkColor, equals(middleGrey.withAlpha(0x8a)));
|
expect(lerp.activeTickMarkColor, equals(middleGrey.withAlpha(0x8a)));
|
||||||
expect(lerp.inactiveTickMarkColor, equals(middleGrey.withAlpha(0x8a)));
|
expect(lerp.inactiveTickMarkColor, equals(middleGrey.withAlpha(0x8a)));
|
||||||
expect(lerp.disabledActiveTickMarkColor, equals(middleGrey.withAlpha(0x1f)));
|
expect(lerp.disabledActiveTickMarkColor, equals(middleGrey.withAlpha(0x1f)));
|
||||||
@ -229,7 +241,7 @@ void main() {
|
|||||||
);
|
);
|
||||||
final SliderThemeData sliderTheme = theme.sliderTheme.copyWith(thumbColor: Colors.red.shade500);
|
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)))!;
|
final MaterialInkController material = Material.of(tester.element(find.byType(Slider)))!;
|
||||||
|
|
||||||
const Radius radius = Radius.circular(2);
|
const Radius radius = Radius.circular(2);
|
||||||
@ -241,10 +253,11 @@ void main() {
|
|||||||
material,
|
material,
|
||||||
paints
|
paints
|
||||||
..rrect(rrect: RRect.fromLTRBAndCorners(24.0, 297.0, 212.0, 303.0, topLeft: activatedRadius, bottomLeft: activatedRadius), color: sliderTheme.activeTrackColor)
|
..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
|
await tester.pumpAndSettle(); // wait for disable animation
|
||||||
|
|
||||||
// The disabled slider thumb is the same size as the enabled thumb.
|
// The disabled slider thumb is the same size as the enabled thumb.
|
||||||
@ -252,7 +265,8 @@ void main() {
|
|||||||
material,
|
material,
|
||||||
paints
|
paints
|
||||||
..rrect(rrect: RRect.fromLTRBAndCorners(24.0, 297.0, 212.0, 303.0, topLeft: activatedRadius, bottomLeft: activatedRadius), color: sliderTheme.disabledActiveTrackColor)
|
..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 Animation<double> enableAnimation,
|
||||||
required TextDirection textDirection,
|
required TextDirection textDirection,
|
||||||
required Offset thumbCenter,
|
required Offset thumbCenter,
|
||||||
|
Offset? secondaryOffset,
|
||||||
bool isDiscrete = false,
|
bool isDiscrete = false,
|
||||||
bool isEnabled = false,
|
bool isEnabled = false,
|
||||||
double additionalActiveTrackHeight = 2.0,
|
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(
|
Widget _buildApp(
|
||||||
SliderThemeData sliderTheme, {
|
SliderThemeData sliderTheme, {
|
||||||
double value = 0.0,
|
double value = 0.0,
|
||||||
|
double? secondaryTrackValue,
|
||||||
bool enabled = true,
|
bool enabled = true,
|
||||||
int? divisions,
|
int? divisions,
|
||||||
}) {
|
}) {
|
||||||
@ -1370,6 +1386,7 @@ Widget _buildApp(
|
|||||||
data: sliderTheme,
|
data: sliderTheme,
|
||||||
child: Slider(
|
child: Slider(
|
||||||
value: value,
|
value: value,
|
||||||
|
secondaryTrackValue: secondaryTrackValue,
|
||||||
label: '$value',
|
label: '$value',
|
||||||
onChanged: onChanged,
|
onChanged: onChanged,
|
||||||
divisions: divisions,
|
divisions: divisions,
|
||||||
|
Loading…
x
Reference in New Issue
Block a user