Flutter实战自定义滚动条

Posted mengqd

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Flutter实战自定义滚动条相关的知识,希望对你有一定的参考价值。

技术图片

老孟导读:【Flutter实战】系列文章地址:http://laomengit.com/guide/introduction/mobile_system.html

默认情况下,Flutter 的滚动组件(比如 ListView)没有显示滚动条,使用 Scrollbar 显示滚动条:

Scrollbar(
  child: ListView.builder(
    reverse: false,
    itemBuilder: (BuildContext context, int index) {
      return Card(
        child: Container(
          height: 45,
          alignment: Alignment.center,
          child: Text(‘$index‘),
        ),
      );
    },
    itemCount: 30,
    itemExtent: 50,
  ),
)

技术图片

在滑动的过程中,右侧显示滚动条,然而 Scrollbar 无法实现自定义滚动条的样式,比如实现如下滚动条样式,

技术图片

这时需要自定义一个滚动条组件。

实现自定义滚动条组件首先需要监听滚动组件 滚动的位置,使用 NotificationListener 监听滚动的位置:

bool _handleScrollNotification(ScrollNotification notification) {
    final ScrollMetrics metrics = notification.metrics;
    print(‘滚动组件最大滚动距离:${metrics.maxScrollExtent}‘);
    print(‘当前滚动位置:${metrics.pixels}‘);
    return true;
  }

  @override
  Widget build(BuildContext context) {
    return NotificationListener<ScrollNotification>(
      onNotification: _handleScrollNotification,
      child: ListView.builder(
        reverse: false,
        itemBuilder: (BuildContext context, int index) {
          return Card(
            child: Container(
              height: 45,
              alignment: Alignment.center,
              child: Text(‘$index‘),
            ),
          );
        },
        itemCount: 30,
        itemExtent: 50,
      ),
    );
  }

通过 ScrollNotification 获取当前滚动组件最大滚动距离和当前滚动位置,其中 metrics.maxScrollExtent 表示当前滚动组件最大滚动距离,metrics.pixels 表示当前滚动位置。

通过这两个值计算滚动条在当前屏幕的位置,通过 Stack 组件 将 ListView 和 自定义的滚动条进行叠加显示:

NotificationListener<ScrollNotification>(
  onNotification: _handleScrollNotification,
  child: Stack(
    alignment: Alignment.topRight,
    children: <Widget>[
      ListView.builder(
        reverse: false,
        itemBuilder: (BuildContext context, int index) {
          return Card(
            child: Container(
              height: 45,
              alignment: Alignment.center,
              child: Text(‘$index‘),
            ),
          );
        },
        itemCount: 30,
        itemExtent: 50,
      ),
      //滚动条
      Container(
        height: 100,
        width: 20,
        color: Colors.red,
      )
    ],
  ),
)

技术图片

将此滚动条和 NotificationListener 监听到的滚动事件联动,通过 Container 的 alignment 属性控制滚动条的位置:

Container(
  alignment: Alignment(1, _alignmentY),
  padding: EdgeInsets.only(right: 5),
  child: Container(
    height: 100,
    width: 20,
    color: Colors.red,
  ),
)

_alignmentY 就是计算出的偏移位置,计算方法如下:

_alignmentY = -1 + (metrics.pixels / metrics.maxScrollExtent) * 2;

这里要注意 alignment 的坐标系:

技术图片

最终效果:

技术图片

然后只需修改滚动条的样式即可:

class _ScrollBar extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Container(
      width: 18,
      height: 60,
      decoration: BoxDecoration(
          shape: BoxShape.rectangle,
          borderRadius: BorderRadius.all(Radius.circular(20)),
          color: Colors.blue),
      child: Column(
        mainAxisAlignment: MainAxisAlignment.center,
        children: <Widget>[
          Icon(
            Icons.arrow_drop_up,
            size: 18,
          ),
          Icon(
            Icons.arrow_drop_down,
            size: 18,
          ),
        ],
      ),
    );
  }
}

技术图片

最后将代码封装,就可以给所有的滚动组件添加自定义的滚动条,而不仅仅是 ListView。

交流

老孟Flutter博客地址(330个控件用法):http://laomengit.com

欢迎加入Flutter交流群(微信:laomengit)、关注公众号【老孟Flutter】:

技术图片 技术图片

以上是关于Flutter实战自定义滚动条的主要内容,如果未能解决你的问题,请参考以下文章

Flutter 自定义组件实战

Flutter导航栏自定义效果

Flutter 自定义组件实战

Flutter,自定义滚动效果

Flutter 如何在使用自定义滚动视图时(或内部)显示自定义剪辑器

选择框的自定义滚动条