Flutter中的Slider

更改Slider样式

要改变Flutter中默认的Slider的滑块样式,需要在Slider外包裹一层SliderTheme,在data中修改thumbShape。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
SliderTheme(
data: SliderTheme.of(context).copyWith(
trackHeight: 10.w, // 进度条轨道高度
thumbShape: MySliderThumbShape(enabledThumbRadius: 8.w, disabledThumbRadius: 5.w), //滑块
overlayShape: RoundSliderOverlayShape(overlayRadius: 7.w),
),
child: Slider(
value: voice.toDouble(),
min: 0,
max: 100,
divisions: 100,
activeColor: ColorConfig.color_2877FD, // 滑块左边轨道的颜色
inactiveColor: ColorConfig.color_F7F7F7, // 滑块右边轨道的颜色
onChanged: (v) {
// TODO
},
),
);

自定义滑块

thumbShape接受一个SliderComponentShape,因此自定义的滑块要继承该类,并实现getPreferredSizepaint两个方法。

其中Size getPreferredSize(bool isEnabled, bool isDiscrete)要返回滑块的大小,isEnabled为滑块是否被按下。

void paint方法中实现滑块的绘制。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
/// 自定义的音量Slider滑块
class MySliderThumbShape extends SliderComponentShape {
const MySliderThumbShape({
this.elevation = 5,
this.pressedElevation = 20,
this.enabledThumbRadius = 8,
this.disabledThumbRadius,
});

final double elevation;
final double pressedElevation;
final double enabledThumbRadius;
final double? disabledThumbRadius;

double get _disabledThumbRadius => disabledThumbRadius ?? enabledThumbRadius;

@override
Size getPreferredSize(bool isEnabled, bool isDiscrete) {
return Size.fromRadius(
isEnabled ? enabledThumbRadius : _disabledThumbRadius);
}

@override
void paint(
PaintingContext context,
Offset center, {
required Animation<double> activationAnimation,
required Animation<double> enableAnimation,
required bool isDiscrete,
required TextPainter labelPainter,
required RenderBox parentBox,
required SliderThemeData sliderTheme,
required TextDirection textDirection,
required double value,
required double textScaleFactor,
required Size sizeWithOverflow,
}) {
final Canvas canvas = context.canvas;

// 阴影的补间值
final Tween<double> elevationTween = Tween<double>(
begin: elevation,
end: pressedElevation,
);
// 阴影的瞬时值
final double evaluatedElevation =
elevationTween.evaluate(activationAnimation);

// 滑块半径大小的补间值
final Tween<double> radiusTween = Tween<double>(
begin: _disabledThumbRadius,
end: enabledThumbRadius,
);
// 滑块半径大小的瞬时值
final double radius = radiusTween.evaluate(enableAnimation);

final Path path = Path();
path.addArc(
Rect.fromCenter(center: center, width: 2 * radius, height: 2 * radius),
0,
pi * 2,
);

canvas.drawShadow(path, Colors.black, evaluatedElevation, true);
canvas.drawCircle(
center,
(radius + 2) * (1 + activationAnimation.value * 0.5),
Paint()..color = Colors.white,
);
canvas.drawCircle(
center,
radius * (1 + activationAnimation.value * 0.5),
Paint()..color = ColorConfig.color_2877FD,
);
}
}