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();
  }
}

要说的主要有两个点:

  1. 定义 sliderValue 为 obs 类型。
  2. 在取最大值时,至少为 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 的方式。虽然没什么动画,但对我来说够用了。

但是好像如果只是自己的项目用,还不如放在项目内部,方便更改。