flutter 滚动的基石 scrollable

简介: flutter 滚动的基石 scrollable

scrollable 是一个 widget,提供滚动的功能。虽然很少会直接使用 scrollable,但是掌握 scrollable, 对掌握使用它的 ListView 等组件会有极大的帮助。

我们先用 scrollable 举一个例子,让内容滚动起来。

MaterialApp(home: SafeArea(
      child: Scaffold(body: Scrollable(viewportBuilder: (context, position) {
        return Viewport(offset: position, slivers: [
          SliverList(delegate: SliverChildBuilderDelegate(
            (context, index) {
              return ListTile(
                title: Text('$index'),
              );
            },
          )),
        ]);
      }))))
复制代码

在这个基础上,我们可以添加修改 scrollable 的各种参数看一下效果。

  • axisDirection 滚动的方向。 默认值是 AxisDirection.down。
  • controller 滚动控制器。用来控制滚动的位置。
  • physics 规定 Scrollable widget 的 physics。比如规定当滚动超出范围时的行为,
  • viewportBuilder 返回一个 viewport
  • incrementCalculator 用键盘操作滚动的时候,用它来计算滚动距离
  • restorationId 用来恢复滚动位置的 key。只有意外退出才会有恢复功能,主动退出不恢复。
  • scrollBehavior 规定 Scrollable widget 的行为。
  • clipBehavior 剪裁内容,默认是 Clip.hardEdge

physics

我们先看一下 physics 的属性。有的属性我们一般是不用到的,但对于读懂源代码是很有用的。

allowImplicitScrolling

当执行 RenderObject.showOnScreen 的时候,是否允许滚动。

举个例子:在一个滚动 widget中 原本一个文本框是不可见的,当获得焦点的时候,如果 allowImplicitScrolling is true,会发生滚动,让 文本框能完全显示。 、

dragStartDistanceMotionThreshold

这是一个f阈值,拖动多少距离触发滚动。如果 是 null ,就没有任何限制。

maxFlingVelocity

这是一个限定值,滚动速度不要太快。

minFlingDistance

最小滚动距离。要么不动,要滚动就至少是这个距离。

minFlingVelocity

最小滚动速度。

parent

合并其它类型 physics。

const BouncingScrollPhysics(parent:const AlwaysScrollableScrollPhysics())
复制代码

方法 applyTo 也有同样的效果

var physics = BouncingScrollPhysics();
physics.applyTo(const AlwaysScrollableScrollPhysics())
复制代码

physics 的值获取过程是这样的。优先取 scrollable 的属性,如果为 null 取 scrollBehavior 的 physics。如果 scrollBehavior 也为 null 取 ScrollConfiguration 的值。(这段需要再看下代码)

viewport

scrollable 提供滚动功能,viewport 负责展示内容。下面解说一下 viewport 的参数

  • axisDirection 默认值 AxisDirection.down 内容的伸展方向是由上到下。这个值一般和 scrollable 的 axisDirection 需要保持一致。
  • crossAxisDirection 和 AxisDirection 垂直的方向。
  • anchor 在没有滚动的情况下,内容距离起始边界的距离, 默认值 0。取值范围[0,1],比如取值 0.5 内容距离起始边界 50%的距离。
  • offset 指导哪些内容显示出来。
  • slivers 滚动的内容。
  • center 是一个 key。如果 center 不为 null ,滚动内容 slivers 是一个 list。slivers 中必须有一个 直属 item 的 key 和 center 相等。这个 item 会被显示在距离起始边界为 0 的位置。
  • cacheExtent 缓存的距离。有两种模式 CacheExtentStyle.pixel,CacheExtentStyle.viewport
  • cacheExtentStyle 指定缓存模式

举一个 center的例子。

center is null center is ValueKey(1)

image.png


var key =const ValueKey(1);
MaterialApp(home: SafeArea(
      child: Scaffold(body: Scrollable(viewportBuilder: (context, position) {
        return Viewport(center: key, offset: position, slivers: [
          SliverList(
            delegate: SliverChildBuilderDelegate((context, index) {
              return ListTile(
                title: Text('$index'),
              );
            }, childCount: 5),
          ),
          SliverToBoxAdapter(
            key: key,
            child: Container(
              height: 100,
              color: Colors.blue,
            ),
          ),
          SliverList(
            delegate: SliverChildBuilderDelegate((context, index) {
              return ListTile(
                title: Text('$index'),
              );
            }, childCount: 12),
          ),
        ]);
      }))
 ));
复制代码

scrollBehavior

scrollBehavior 是用来描述滚动行为的。scrollBehavior 可以直接给 scrollable赋值,也可以由 ScrollConfiguration 来影响它的 subtree。ScrollConfiguration 是 inheritWidget,它有 scrollBehavior 属性,所以 subtree 都可以得到 scrollBehavior。

为了自定义滚动行为,你需要新建 class extends from scrollBehavior。举个自定义 physics 和 overscrollIndicator 的例子。 用了 MyScrollBehavior 后,无论内容多少,都可以滚动,overscroll 不再有提示。原来 android 在 overflow 的时候会出现的蓝色波浪提示就不会出现了。

class MyScrollBehavior extends ScrollBehavior {
  @override
  ScrollPhysics getScrollPhysics(BuildContext context) {
    return const AlwaysScrollableScrollPhysics();
  }
  @override
  Widget buildOverscrollIndicator(
      BuildContext context, Widget child, ScrollableDetails details) {
    return const SizedBox.shrink();
  }
}
复制代码

用的时候可以直接在 scrolable 构造函数中传入,也可以放在 ScrollConfiguration 中影响 subtree.

监听滚动行为

Scrollable Widget 在滚动的时候,会发滚动事件出来,用 NotificationListener 来监听。滚动事件分下面几种

上面四个都是 ScrollNotification 的子类,还有一个不是它的子类,但也会用到 当 viewport 的尺寸改变的时候,会发出ScrollMetricsNotification

NotificationListener<ScrollNotification>(
      onNotification: (notification) {
        //metrics 包含了滚动的详情
        print(notification.metrics);
        //如果不是拖动触发 dragDetails is null. 程序也可以触发滚动。
        print(notification.dragDetails);
        //按事件类型做出响应
        if(notification is ScrollStartNotification){
          ...
        }
        //继续向上层冒泡
        return false;
      },
      child: Scrollable(
      ...
复制代码

metrics 详情

ScrollMetrics 用来描述滚动的详情的。

  1. pixels 当前滚动距离
  2. minScrollExtent 滚动的最小值
  3. maxScrollExtent 滚动的最大值
  4. viewportDimension viewport 的高度(和滚动方向致)
  5. outOfRange 起出滚动范围,这个是一计算值
bool get outOfRange => pixels < minScrollExtent || pixels > maxScrollExtent;
复制代码
  1. atEdge 是否在边缘,是一个计算值。
bool get atEdge => pixels == minScrollExtent || pixels == maxScrollExtent;
复制代码
  1. extentBefore  在viewport 上面超出的高度,是一个计算值。
double get extentBefore => math.max(pixels - minScrollExtent, 0.0);
复制代码
  1. extentInside viewport 内部的高度,是一个计算值
  2. extentAfter viewport 下面的还没有进入的高度,是一个计算值。
double get extentAfter => math.max(maxScrollExtent - pixels, 0.0);
复制代码

到这里就结束了,谢谢观看。基础的部分会很枯燥,但对于后面的学习非常重要,还是要打好基础。

目录
相关文章
|
3月前
|
数据库 容器
Flutter笔记:滚动之-无限滚动与动态加载的实现
Flutter笔记:滚动之-无限滚动与动态加载的实现
195 0
|
11月前
|
存储 数据库 索引
Flutter笔记:滚动之-无限滚动与动态加载的实现(GetX简单状态管理版)
本文介绍Flutter中如何实无线滚动(基于GetX简单状态管理而非有状态组件)
102 0
|
1月前
|
UED
Flutter-无限循环滚动标签
Flutter-无限循环滚动标签
26 0
|
1月前
Flutter 滚动距离来设置TabBar的位置,点击TabBar滚动的到指定的位置
Flutter 滚动距离来设置TabBar的位置,点击TabBar滚动的到指定的位置
|
3月前
|
前端开发 UED 开发者
【Flutter前端技术开发专栏】Flutter中的列表与滚动视图优化
【4月更文挑战第30天】Flutter开发中,优化列表和滚动视图至关重要。本文介绍了几种优化方法:1) 使用`ListView.builder`和`GridView.builder`实现懒加载;2) 复用子组件以减少实例创建;3) 利用`CustomScrollView`和`Slivers`提升滚动性能;4) 通过`NotificationListener`监听滚动事件;5) 使用`KeepAlive`保持列表项状态。掌握这些技巧能提升应用性能和用户体验。
55 1
【Flutter前端技术开发专栏】Flutter中的列表与滚动视图优化
|
3月前
|
存储 缓存 监控
【Flutter前端技术开发专栏】Flutter中的列表滚动性能优化
【4月更文挑战第30天】本文探讨了Flutter中优化列表滚动性能的策略。建议使用`ListView.builder`以节省内存,避免一次性渲染所有列表项。为防止列表项重建,可使用`UniqueKey`或`ObjectKey`。缓存已渲染项、减少不必要的重绘和异步加载大数据集也是关键。此外,选择轻量级组件,如`StatelessWidget`,并利用Flutter DevTools监控性能以识别和解决瓶颈。持续测试和调整以提升用户体验。
97 0
【Flutter前端技术开发专栏】Flutter中的列表滚动性能优化
|
3月前
|
前端开发 数据处理
【Flutter 前端技术开发专栏】Flutter 中的滚动性能优化与无限列表实现
【4月更文挑战第30天】本文探讨了 Flutter 中的滚动性能优化和无限列表实现。关键点包括:1) 滚动性能直接影响用户满意度,优化可提升响应速度;2) 影响因素有布局复杂度、频繁重绘和数据处理;3) 优化措施包括懒加载、简化布局、减少不必要的重绘和高效处理数据;4) 无限列表通过监听滚动位置,动态加载新数据;5) 实现时注意加载策略、数据处理效率和内存管理。案例分析和总结强调了优化在实际开发中的重要性。
61 0
【Flutter 前端技术开发专栏】Flutter 中的滚动性能优化与无限列表实现
|
3月前
|
前端开发
Flutter笔记:光影动画按钮、滚动图标卡片组等
Flutter笔记:光影动画按钮、滚动图标卡片组等
58 0
|
3月前
|
前端开发 JavaScript 定位技术
Flutter vs 前端 杂谈:SliverAppBar、手动实现Appbar、前端Html+JS怎么实现滚动变化型Appbar - 比较
Flutter vs 前端 杂谈:SliverAppBar、手动实现Appbar、前端Html+JS怎么实现滚动变化型Appbar - 比较
63 0
Flutter利用ScrollController获取、控制滚动组件的滚动位置
Flutter利用ScrollController获取、控制滚动组件的滚动位置