【Flutter 组件集录】Scrollbar| 8月更文挑战

前言:

这是我参与8月更文挑战的第 4 天,活动详情查看:8月更文挑战。为应掘金的八月更文挑战,我准备在本月挑选 31 个以前没有介绍过的组件,进行全面分析和属性介绍。这些文章将来会作为 Flutter 组件集录 的重要素材。希望可以坚持下去,你的支持将是我最大的动力~

| 本系列 | 组件文章 | 列表 | | ------------------------------------------------------------ | ------------------------------------------------------------ | ------------------------------------------------------------ | | 1.NotificationListener | 2.Dismissible | 3.Switch | | 4.Scrollbar | 5.ClipPath | 6.CupertinoActivityIndicator | | 7.Opacity | 8.FadeTransition | 9. AnimatedOpacity | | 10. FadeInImage | 11. Offstage | 12. TickerMode | | 13. Visibility | 14. Padding | 15. AnimatedContainer | | 16.CircleAvatar | 17.PhysicalShape | 18.Divider | | 19.Flexible、Expanded 和 Spacer | 20.Card | |


一、Scrollbar 的使用
1. Scrollbar 的效果

ListView 这种可滑动的组件中,默认情况没有右侧的指示器 ,这样用户在滑动中不太容易知道滑动进度。使用 Scrollbar 就可以在 右侧 出现滑动条。如下分别是在 AndroidiOS 的效果,可以看出在不同平台上,Scrollbar 的展示是有所差异的,比如圆角、高度、宽度等。这些我们都能从源码中找到根源。

| Android 平台 | iOS 平台 | | ------------------------------------------------------------ | ------------------------------------------------------------ | | | |

从使用的角度来看,Scrollbar 非常简单,只是在 ListView 外层嵌套一下就行了。然后滑动时就会发现有滚动指示器,这看起来非常神奇。神奇的点在于: ListView 的滑动没有和 Scrollbar 有任何的直接联系, Scrollbar 竟然可以跟随 ListView 的进行滑动。

```dart class ScrollbarDemo extends StatelessWidget { const ScrollbarDemo({Key? key}) : super(key: key);

@override Widget build(BuildContext context) { return Scrollbar( //<--- tag1 child: ListView( children: List.generate( 60, (index) => ItemBox(index: index)).toList()), ); } } ```

这种 可插拔 式的组合,既可以让组件间几乎没有耦合,又可以让一方随另一方进行改变。Scrollbar 虽然在使用上非常简单,但其背后的这套数据通知方案是非常值得我们去研究学习的。


2. Scrollbar 的表现属性

从下面 Scrollbar 的构造函数中可以看出,除了 child 是必传的入参,还有 8 个 参数,这里先看一下 isAlwaysShownthicknessradius 三个决定 Scrollbar 显示的属性。

dart Scrollbar( isAlwaysShown: true, // 是否一直显示 radius: const Radius.circular(3), // 圆角半径 thickness: 6,// 线宽 child: ... );

如下左侧是 安卓平台默认显示 效果,可以看出 Scrollbar 只在滑动过程中显示出来,并且显隐时伴随 透明渐变动画 效果。如下右侧上面三个属性设置后的效果,isAlwaysShown 表示 Scrollbar 是否一直显示;radius 表示 圆角半径thickness 表示 Scrollbar 滑块的宽度。

| 安卓默认显示 | 本案例显示 | | ------------ | ---------- | | | |


3. Scrollbar 的尺寸区域

所有可以显示的组件都会尤其占据的位置区域,大家可以思考一下 Scrollbar 的尺寸是 包括 ListView 的整体,还是只是一个细的长条,或只是一个小滑块。通过 布局查看器 可以看出 Scrollbar 的尺寸是包括 ListView 在内的整个一大片。到这里,我们或多或少可以猜到 Scrollbar 源码在布局上的处理。

| 猜测 | 答案 | | ---- | ---- | | | |


4.可交互性:interactive

如下两幅图分别是 interactive:falseinteractive:true 的效果。它的作用很明显:如果为 true 时,小滑块可以接受拖动事件,来控制列表的滑动。在移动端默认为 false

| interactive:false | interactive:true | | ------------------------------------------------------------ | ------------------------------------------------------------ | | | |


5.回调通知:notificationPredicate

notificationPredicate 是一个回调函数,会将 ScrollNotification 对象回调给使用者,并且返回 bool 值决定是否显示 Scrollbar

```dart @override Widget build(BuildContext context) { return Scrollbar( notificationPredicate: _notificationPredicate, child: ListView( children: List.generate(60, (index) => ItemBox(index: index)).toList()), ); }

bool _notificationPredicate(ScrollNotification notification) { print('----$notification---------'); return true; } ```


6.滑动控制器:controller

如果你只为 ListView 指定了 controller 属性,那么 Scrollbar 则会报错。你必须保证两者有同一个滑动控制器。通过 滑动控制器 我们可以监听列表的滑动,以及控制滑动。


除此之外,showTrackOnHoverhoverThickness 两个属性顾名思义是悬浮时的效果,这一般只在 非移动端 设备上有效果,另外,目前 ListView 在桌面端中默认自带 Scrollbar

到这里 Scrollbar 所有的属性用法就已经介绍完毕。下面简单地看一下 Scrollbar 的源码实现,不止于是知道怎么用,还能对它的内部机制有一点了解,源码中的一些逻辑处理,这或许在某些场景中能对你产生帮助,多了解一些总没什么坏处。知其然,知其所以然,你把握的才够通透


二、Scrollbar 源码简看
1. Scrollbar 类定义

从下面可以看出 Scrollbar 是一个 StatefulWidget ,通过 _ScrollbarState 状态类构建组件。


下面是 _ScrollbarState 的全部代码,通过如果是 iOS 平台,则构建 CupertinoScrollbar,否则构建 _MaterialScrollbar

这是 _ScrollbarState 的全部源码,不过我从这里看不出 Scrollbar 是 StatefulWidget 的必要性。不知你有什么见解。


2. 滑动事件的监听和滑块的移动

CupertinoScrollbar_MaterialScrollbar 都是继承自 RawScrollbar ,也就是说它们的底层逻辑是一样的,只不过根据平台进行一定的适配。


RawScrollbarState 构建组件代码中可以看到,使用了 NotificationListener 监听 ScrollNotification 通知,执行 _handleScrollNotification 方法。如果不了解 NotificationListener 组件,可以看一下第一篇


_handleScrollNotification 中有一些比较核心的逻辑,其中 notificationPredicate 回调会先触发,如果该函数返回 false ,也就意味着_handleScrollNotification 返回 false ,下面的逻辑不会被执行。这也是为什么返回 false 时,滑块不显示的原因。下面会执行透明渐变动画,以及根据 notification 信息更新 scrollbarPainter 画板,这是滑块可以跟随列表滑动最核心的处理。


3.滑块的绘制

RawScrollbarState#build 方法的最后,是通过前景画板 foregroundPainter 进行绘制,child 为传入的 ListView,这也是为什么 Scrollbar 的尺寸区域是整个一片的原因。

绘制的画板是 ScrollbarPainter ,在状态初始化时被创建。


ScrollbarPainter 继承自 ChangeNotifier ,并实现 CustomPainter ,也就是说它既是可监听对象,又是画板,也就说明它自己可以通知进行画板重绘,使用这里 ScrollbarPainter 是以成员变量的方式声明的,在需要更新时,自己执行更新。这也很值得我们学习借鉴,源码是最好的老师。至于具体的绘制逻辑,就不说了,有兴趣的自己看看。

Scrollbar 组件的使用方式到这里就介绍完毕,那本文到这里就结束了,谢谢观看,明天见~

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值