先上效果图:
因为项目需求,所以自定义一个slider.
使用:
MySliderUtil(
minValue: (widget.model?.durableNow ?? 0) / 100, //可滑动的最小值
valueBlock: (value) {
print(value);
),
具体代码
class MySliderUtil extends StatefulWidget {
MySliderUtil({
Key? key,
required this.valueBlock,
this.minValue = 0.0,
}) : super(key: key);
final ValueBlock valueBlock;
final double minValue;
@override
_MySliderUtilState createState() => _MySliderUtilState();
}
class _MySliderUtilState extends State<MySliderUtil> {
double _value = 0.0;
@override
void initState() {
// TODO: implement initState
super.initState();
_value = widget.minValue;
}
@override
Widget build(BuildContext context) {
return SizedBox(
height: SAdapt.width(28),
child: Stack(
children: [
Positioned(
top: 8.w,
child: Container(
width: 12.w,
height: 12.w,
decoration: BoxDecoration(
color: get826DD4Color(),
borderRadius: BorderRadius.circular(10),
),
),
),
Positioned(
right: 0.w,
top: 8.w,
child: Container(
width: 12.w,
height: 12.w,
decoration: BoxDecoration(
color: getF5F9FCColor(),
borderRadius: BorderRadius.circular(10),
),
),
),
Container(
margin: EdgeInsets.only(left: 11.5.w, right: 11.5.w),
child: SliderTheme(
data: SliderThemeData(
//去掉长按光晕
overlayColor: Colors.transparent,
trackHeight: SAdapt.width(2),
inactiveTrackColor: getF5F9FCColor(),
activeTrackColor: get826DD4Color(), // Color(0xFF81C359),
trackShape: const CustomTrackShape(),
thumbShape: SquareSliderComponentShape(),
),
child: Slider(
value: _value < 0 ? 0 : _value,
onChangeStart: (double value) {},
onChangeEnd: (double value) {
if (value < widget.minValue) {
widget.valueBlock(widget.minValue);
return;
}
//每次借宿后都会走
// 拖拽跳转
setState(() {
_value = value;
});
widget.valueBlock(value);
},
onChanged: (double value) {
if (value < widget.minValue) {
_value = widget.minValue;
} else {
_value = value;
}
setState(() {});
},
),
),
),
],
),
);
}
}
上面的其实就可以用了,但是需求的滑块需要我们自定义,又遇到了别的问题,一步一步来~!
使用的时候发现滑块选中的偏移量有一些问题,所以定义了如下的RoundedRectSliderTrackShape
:
class CustomTrackShape extends RoundedRectSliderTrackShape {
const CustomTrackShape();
@override
Rect getPreferredRect({
required RenderBox parentBox,
Offset offset = Offset.zero,
required SliderThemeData sliderTheme,
bool isEnabled = false,
bool isDiscrete = false,
}) {
final double trackHeight = sliderTheme.trackHeight!;
final double trackWidth = parentBox.size.width;
final double trackLeft = offset.dx;
final double trackTop =
offset.dy + (parentBox.size.height - trackHeight) / 2;
return Rect.fromLTWH(trackLeft, trackTop, trackWidth, trackHeight);
}
@override
void paint(
PaintingContext context,
Offset offset, {
required RenderBox parentBox,
required SliderThemeData sliderTheme,
required Animation<double> enableAnimation,
required TextDirection textDirection,
required Offset thumbCenter,
bool isDiscrete = false,
bool isEnabled = false,
double additionalActiveTrackHeight = 0,
}) {
super.paint(
context,
offset,
parentBox: parentBox,
sliderTheme: sliderTheme,
enableAnimation: enableAnimation,
textDirection: textDirection,
thumbCenter: thumbCenter,
//增加选中滑块的高度,系统默认+2· 给0就不加高了
additionalActiveTrackHeight: 0,
);
}
}
最后我们来封装滑块的样式:
class SquareSliderComponentShape extends SliderComponentShape {
@override
Size getPreferredSize(bool isEnabled, bool isDiscrete) {
return Size(SAdapt.width(28), SAdapt.width(28));
}
@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;
canvas.drawRRect(
RRect.fromRectAndRadius(
Rect.fromCenter(
center: center, width: SAdapt.width(28), height: SAdapt.width(28)),
const Radius.circular(14),
),
Paint()..color = Colors.white,
);
//背景的线 实线
Paint line = Paint()
..color = get826DD4Color()
..strokeCap = StrokeCap.round
..style = PaintingStyle.stroke
..strokeWidth = SAdapt.width(2);
// 画圆方法
canvas.drawCircle(center, SAdapt.width(14), line);
}
}
如果对你有帮助的话,希望能给我点个赞,哈哈!
后续
项目里好多样式的滑块,后来引用了一个第三方:syncfusion_flutter_sliders
,然后按照你的需求再进行修改就可以了.
进度条 两个拖动
#https://pub.dev/packages/syncfusion_flutter_sliders/versions
syncfusion_flutter_sliders: ^20.3.52
修改进度条样式
# https://pub.dev/packages/syncfusion_flutter_core
syncfusion_flutter_core: ^20.3.52
有各式各样的,大致都能满足我们使用的需求.下面是文档:
https://help.syncfusion.com/flutter/slider/thumb-and-overlay
贴两个使用的例子:
这个是双滑块的
先上效果图
代码:
Container(
margin: EdgeInsets.only(
bottom: SAdapt.width(15),
left: SAdapt.width(15),
right: SAdapt.width(15),
),
child: Stack(
children: [
Positioned(
// right: 21.w,
left: 14.w,
top: 19.w,
child: Container(
width: 12.w,
height: 12.w,
decoration: BoxDecoration(
color: getF5F9FCColor(),
borderRadius: BorderRadius.circular(10),
),
),
),
Positioned(
// right: 21.w,
right: 14.w,
top: 19.w,
child: Container(
width: 12.w,
height: 12.w,
decoration: BoxDecoration(
color: getF5F9FCColor(),
borderRadius: BorderRadius.circular(10),
),
),
),
SfRangeSliderTheme(
data: SfRangeSliderThemeData(
overlayColor: Colors.transparent,
thumbColor: Colors.white,
thumbRadius: 12,
thumbStrokeWidth: SAdapt.width(2),
thumbStrokeColor: get826DD4Color(),
activeTrackHeight: SAdapt.width(2),
inactiveTrackHeight: SAdapt.width(2),
activeTrackColor: get826DD4Color(),
),
child: SfRangeSlider(
min: 0.0,
max: widget.maxRang,
values: _values,
interval: 20,
showTicks: false,
showLabels: false,
enableTooltip: false,
minorTicksPerInterval: 1,
// activeColor: get826DD4Color(),
inactiveColor: getF5F9FCColor(),
onChanged: (SfRangeValues values) {
setState(() {
selectedStart = int.parse(moneyDoubleOrInt(
(_values.start).toDouble(),
postion: 0));
selectedEnd = int.parse(moneyDoubleOrInt(
(_values.end).toDouble(),
postion: 0));
// if (selectedEnd == selectedStart) {
// _values = const SfRangeValues(0, 1);
// } else {
_values = values;
// }
});
},
),
),
],
),
),
这个是单滑块的效果图跟我们之前使用的 一样,但是他的最小值定义完之后,就不是从0开始了,你给完最小值 就是初始阶段,而不是可使用的最小值.我自定义的起始值就是0,然后在给一个最小值是显示出来的,只可以在我给的最小值之间和最大值之间滑动
Container(
margin: EdgeInsets.only(
left: SAdapt.width(10),
right: SAdapt.width(10),
),
child: Stack(
children: [
Positioned(
// right: 21.w,
left: 14.w,
top: 19.w,
child: Container(
width: 12.w,
height: 12.w,
decoration: BoxDecoration(
color: get826DD4Color(),
borderRadius: BorderRadius.circular(10),
),
),
),
Positioned(
// right: 21.w,
right: 14.w,
top: 19.w,
child: Container(
width: 12.w,
height: 12.w,
decoration: BoxDecoration(
color: getF5F9FCColor(),
borderRadius: BorderRadius.circular(10),
),
),
),
SfSliderTheme(
data: SfSliderThemeData(
//光晕颜色
overlayColor: Colors.transparent,
thumbColor: Colors.white,
thumbRadius: 12,
thumbStrokeWidth: SAdapt.width(2),
thumbStrokeColor: get826DD4Color(),
activeTrackHeight: SAdapt.width(2),
inactiveTrackHeight: SAdapt.width(2),
activeTrackColor: get826DD4Color(),
),
child: SfSlider(
min: 0.0,
max: 10.0,
value: sliderNum,
interval: 20,
minorTicksPerInterval: 1,
inactiveColor: getF5F9FCColor(),
onChanged: (newValue) {
setState(() {
sliderNum = newValue;
});
},
),
),
],
),
),