简述
首先说下非常抱歉,因为个人问题,已有一个多月没有更新了,上周五有个小姐姐问我一个分段滑块的效果,这里就简单写下一个小样作为一个记录。
效果图
分析
其实自带的Slider基本能满足我们的需求,但是这个小姐姐的需要是后台会返回一个数组段比如说[0,10,30,60,100,150],这个滑块只能滑动到数组段中的值,其实这个简单的方式就是直接在slider滑动的时候,判断当前value距离数组段中那个值最接近,然后直接设置slider的值为这个值就可以了。
代码实现
///在数组段中找到当前与value最接近的值 void updateValue(double value) { var minValue = double.infinity; var result = 0.0; for (var element in widget.divisions) { double m = value - element; if (m.abs() < minValue) { result = element; minValue = m.abs(); } } if (_value == result) { return; } setState(() { _value = result; if (widget.onChanged != null) { widget.onChanged?.call(_value); } }); }
完整代码
import 'package:flutter/material.dart'; ///分段滑块 class DivisionsSlider extends StatefulWidget { const DivisionsSlider({ Key? key, required this.value, required this.onChanged, required this.divisions, this.onChangeStart, this.onChangeEnd, this.min = 0.0, this.max = 1.0, this.label, this.activeColor, this.inactiveColor, this.thumbColor, this.mouseCursor, this.semanticFormatterCallback, this.focusNode, this.autofocus = false, }) : super(key: key); final double value; final ValueChanged<double>? onChanged; final ValueChanged<double>? onChangeStart; final ValueChanged<double>? onChangeEnd; final double min; final double max; final String? label; final Color? activeColor; final Color? inactiveColor; final Color? thumbColor; final MouseCursor? mouseCursor; final SemanticFormatterCallback? semanticFormatterCallback; final FocusNode? focusNode; final bool autofocus; final List<double> divisions; @override State<DivisionsSlider> createState() => _DivisionsSliderState(); } class _DivisionsSliderState extends State<DivisionsSlider> { late double _value; @override void initState() { super.initState(); _value = widget.value; } @override Widget build(BuildContext context) { return Slider( value: _value, onChanged: (value) { updateValue(value); }, onChangeStart: widget.onChangeStart, onChangeEnd: widget.onChangeEnd, min: widget.min, max: widget.max, label: widget.label, activeColor: widget.activeColor, inactiveColor: widget.inactiveColor, thumbColor: widget.thumbColor, mouseCursor: widget.mouseCursor, semanticFormatterCallback: widget.semanticFormatterCallback, focusNode: widget.focusNode, autofocus: widget.autofocus, ); } void updateValue(double value) { var minValue = double.infinity; var result = 0.0; for (var element in widget.divisions) { double min = (value - element).abs(); if (min < minValue) { result = element; minValue = min; } } if (_value == result) { return; } setState(() { _value = result; if (widget.onChanged != null) { widget.onChanged?.call(_value); } }); } }
使用控件
DivisionsSlider( value: defaultValue, onChanged: (value) { defaultValue = value; setState(() {}); }, divisions: const [0, 10, 30, 60, 100, 150], max: 150, ),