Flutter | 你真的会用 Slider 组件吗?

Slider 用在哪里?

当你接触到一个 flutter 组件时,首先要考虑的是它的应用场景,而不是看到什么就学什么,flutter 的组件目前已经快接近 400 个了,想要全部了解他们是不可能的,常用的做法是根据你的实际需求去寻找对应的组件使用,慢慢用你就会熟悉越来越多的组件,完全没必要去花时间去一个个过一遍,总之这样的学习方式是不对的。

Slider 是 flutter 中的滑块组件,常用的场景有音乐播放进度条、系统音量调节、屏幕亮度调节等。凡是和进度有关的场景,读者都可以尝试用一下这个组件。如下面的效果,都是可以用 Slider 来实现的。


音乐播放器
音量调节

Slider 基本使用

Slider 的组成大致有:轨道、滑块、刻度、标签。如下图

Slider 基本组成

下面代码是 Slider 组件最简单的使用方法,直接声明了一个 Slider,呈现出来的效果如上图。注意 label 标签属性只有声明了 divisions 属性才会生效,否则不显示。

      body: Slider(
        value: _value,
        min: 0, // 滑动范围最小值
        max: 100, // 滑动范围最大值
        // 用了 divisions 滑动范围就是离散的,把 100 分成 10 个等长范围,
        // 每次滑动的最小单元是下一个离散点,我喜欢叫做刻度,便于理解,比如这里是 10 个刻度
        divisions: 10,
        label: "$_value", // 标签
        activeColor: Colors.blue, // 激活部分的轨道颜色
        inactiveColor: Colors.grey, // 未激活轨道部分的颜色
        onChanged: (value){ // 滑动滑块时的回调函数
          setState(() {
            _value = value;
          });
        },
      )

使用 SliderTheme,滑块主题

Slider 的使用难道就这么简单吗,答案显然不是。上面直接声明一个 Silder 并使用,只能算是生成了 Slider 的 4 个基本组成部分(轨道、滑块、标签、刻度)。如何对这些基本结构定制化呢?比如我想让轨道的大小、颜色、形状按照 UI 出图来决定,那么 SlideTheme 就上场了,在实际开发中,基本都是用 SlideTheme 来包装 Slider 使用。

简单点说,就是使用 SliderTheme 可以自定义 Slider 各个组件的颜色和形状,提供了更好的扩展性。

下面代码是 SliderTheme 的基本使用方法。

      body: SliderTheme(
        data: SliderTheme.of(context).copyWith(
          trackHeight: 10, // 轨道高度
          trackShape: RectangularSliderTrackShape(), // 轨道形状,可以自定义
          activeTrackColor: Colors.blueGrey, // 激活的轨道颜色
          inactiveTrackColor: Colors.black26,  // 未激活的轨道颜色
          thumbShape: RoundSliderThumbShape( //  滑块形状,可以自定义
              enabledThumbRadius: 30  // 滑块大小
          ),
          thumbColor: Colors.white, // 滑块颜色
          overlayShape: RoundSliderOverlayShape(  // 滑块外圈形状,可以自定义
            overlayRadius: 50, // 滑块外圈大小
          ),
          overlayColor: Colors.black54, // 滑块外圈颜色
          valueIndicatorShape: PaddleSliderValueIndicatorShape(), // 标签形状,可以自定义
          activeTickMarkColor: Colors.red,  // 激活的刻度颜色
        ),
        child: Slider(
          value: _value,
          min: 0,
          max: 100,
          divisions: 10,
          label: '$_value',
          onChanged: (v){
            setState(() {
              _value = v;
            });
          },
        ),
      ),

呈现出来的效果是这样的。


SliderTheme

介绍 Slider 的使用方法绝对不是本文的目的。细心的读者可能会发现,在上图中,Slider 的轨道(track)宽度并没有占满水平方向,左右还留有空间。读者在直观上可能会认为是轨道自带了外边距(margin)或内边距(padding),其实都不是!左右留有的空间是 Slider 的大小,Slider 占据了整个屏幕的水平宽度。留出的左右空白大小,刚好是滑块外圈直径的大小!滑块滑到最左或最右,能保证滑块仍然在 Slider 内部,仅此而已,如下图。

SliderTheme

如何让轨道宽度和 Slider 一样?

读者用过某音,某狗的音乐播放器,某牙、某站的视频播放器,会发现一个共性:他们的滑块是不会超过轨道的。既然有了上面的问题,那么如何解决呢?以正常的角度来看问题,本质是轨道的宽度不够导致的,那么我们让轨道的宽度和 Slider 保持一致,问题就迎刃而解了。

Slider 各个组件(轨道、滑块、标签、刻度)的形状都是可以自定义的,Slider 轨道形状默认是圆角,即(RoundedRectSliderTrackShape),通过继承 RoundedRectSliderTrackShape 重写 getPreferredRect 方法,我们就能很容易的对轨道的宽度、高度做出调整。

class FullWidthTrackShape extends RoundedRectSliderTrackShape {
  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 trackLeft = offset.dx;
    final double trackTop = offset.dy + (parentBox.size.height - trackHeight) / 2;
    // 让轨道宽度等于 Slider 宽度
    final double trackWidth = parentBox.size.width;
    return Rect.fromLTWH(trackLeft, trackTop, trackWidth, trackHeight);
  }
}

上面代码 FullWidthTrackShape 继承了 RoundedRectSliderTrackShape 并重写了 getPreferredRect 方法,让轨道的宽度和 Slider一样。

代码写好了,那就试试,将

trackShape: RectangularSliderTrackShape(), // 轨道形状,可以自定义

改为我们刚刚自定义的 FullWidthTrackShape

trackShape: FullWidthTrackShape(), // 轨道形状,可以自定义

来看看效果怎么样,如下图。现在我们让轨道的宽度和 Slider 一样了,是不是很开心。


SliderTheme

Slider,如何沿垂直方向滑动?

告别了上面一个小难题,我现在要讲讲如何让 Slider 沿垂直方向滑动。在你看过所有关于 Slider 组件使用的教程中,基本都是一个组件从左滑到右,滑到全文结束。本文希望从不一样的角度来讲解该如何让 Slider 沿垂直方向滑动。

方法其实很简单,利用 RotatedBox 旋转组件就行了,这个组件很简单,被它包裹的组件可以沿中心轴顺时针旋转,最小旋转角度是90°,即 1/4 圈。来看看下面的代码,顺时针旋转了 3/4 圈,Slider 就可以从下到上沿垂直方向滑动了。读者到这应该可以得到一个启发,在 flutter 中,各种组件的合理组合使用,可以实现意想不到的效果。

      body: RotatedBox(
        quarterTurns: 3,
        child: SliderTheme(
          data: SliderTheme.of(context).copyWith(
            trackHeight: 10, // 轨道高度
            trackShape: FullWidthTrackShape(), // 轨道形状,可以自定义
            activeTrackColor: Colors.blueGrey, // 激活的轨道颜色
            inactiveTrackColor: Colors.black26,  // 未激活的轨道颜色
            thumbShape: RoundSliderThumbShape( //  滑块形状,可以自定义
                enabledThumbRadius: 30  // 滑块大小
            ),
            thumbColor: Colors.white, // 滑块颜色
            overlayShape: RoundSliderOverlayShape(  // 滑块外圈形状,可以自定义
              overlayRadius: 50, // 滑块外圈大小
            ),
            overlayColor: Colors.black54, // 滑块外圈颜色
            valueIndicatorShape: PaddleSliderValueIndicatorShape(), // 标签形状,可以自定义
            activeTickMarkColor: Colors.red,  // 激活的刻度颜色
          ),
          child: Slider(
            value: _value,
            min: 0,
            max: 100,
            divisions: 10,
            label: '$_value',
            onChanged: (v){
              setState(() {
                _value = v;
              });
            },
          ),
        ),
      )
垂直滑动

写在最后

其实网上有大把介绍组件使用的书籍和教程,甚至有很多开源的组件项目来学习,读者可以从这些书籍中获取它们基本的使用方法。但是这些基础知识在项目中就真的够用了吗?答案肯定是不够用,在项目开发过程中,你会遇到各种各样的问题,这都要需要你从现有的工具来找出问题的解决方法,所以很多时候并不是代码能力上的差异,更多时候是想问题的角度和思维方式。

如果你对我感兴趣,请移步到 http://blogss.cn ,进一步了解。

  • 如果本文帮助到了你,欢迎点赞和关注 ❤️
  • 由于作者水平有限,文中如果有错误,欢迎在评论区指正 ✔️
  • 本文首发于简书,未经许可禁止转载 ©️
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 211,123评论 6 490
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,031评论 2 384
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 156,723评论 0 345
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,357评论 1 283
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,412评论 5 384
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,760评论 1 289
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,904评论 3 405
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,672评论 0 266
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,118评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,456评论 2 325
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,599评论 1 340
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,264评论 4 328
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,857评论 3 312
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,731评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,956评论 1 264
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,286评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,465评论 2 348

推荐阅读更多精彩内容