flutter 实现无极滑动条
项目地址:https://github.com/p1gd0g/infinite_slider
背景
做需求时经常遇到一种情况,需要通过 slider 选择数字,但是上下限并不是固定的。例如说,我们在调整网格交易网格大小时,理论上格子可以无限大,他的上限就是不固定的。
之前我的处理方法是,通过额外的 input 组件控制上限。缺点很明显,增加了用户认知成本。
所以我做了一个简单的无极滑动条。注意,是“无极”而不是“无级”。
介绍
这个组件很简单,首先它是基于 getx 的,方便组件的刷新。这可能有些重度,但就我的项目而言,还不需要考虑那么多。
数据
定义他的数据类:
class InfiniteSliderData {
InfiniteSliderData(this.value);
double value;
var sliderValue = 0.5.obs;
double min() {
return value * 0.3;
}
double max() {
if (value <= 0) {
return 1;
}
return value * 1.7;
}
double current() {
return sliderValue.value * (max() - min()) + min();
}
}
要说的主要有两个点:
- 定义 sliderValue 为 obs 类型。
- 在取最大值时,至少为 1,避免滑动条进入死区。
组件
然后是他的 build 部分,最外层是一个 card,card是我非常喜欢的一个组件,他能为里面的组件生成一个边界,看起来美观一些。
card 内层是一个 column,包含了标题和一个 row。row 内部包含了 min 值和 max 值,还有中间的 slider。slider 套了一个 expanded 是为了让他长度占满整行。text 外层的 padding 仅仅是为了美观。
要注意的是所有数值保持一样的方法进行取整,避免计算时出现不一致。
@override
Widget build(BuildContext context) {
return Obx(
() => Card(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text(titleFormater?.call(data.current().round().toString()) ??
data.current().round().toString()),
Row(mainAxisAlignment: MainAxisAlignment.center, children: [
Padding(
padding: const EdgeInsets.all(8.0),
child: Text(data.min().round().toString()),
),
Expanded(
child: Slider(
onChanged: (value) {
data.sliderValue.value = value;
},
onChangeEnd: (value) {
data.value = data.current().round().toDouble();
data.sliderValue.value = 0.5;
},
value: data.sliderValue.value,
),
),
Padding(
padding: const EdgeInsets.all(8.0),
child: Text(data.max().round().toString()),
),
]),
],
),
),
);
}
发布
如果你曾经设置了 $env:PUB_HOSTED_URL="https://pub.flutter-io.cn"
,一定要记得改回来,不然是无法发布的。
或者在当前终端临时改回来 $env:PUB_HOSTED_URL="https://pub.dev"
,然后再 flutter pub publish
。这样可以避免修改环境变量。
总结
这是我的第一个包,也算是重新巩固了 dart publish package 的方式。虽然没什么动画,但对我来说够用了。
但是好像如果只是自己的项目用,还不如放在项目内部,方便更改。