0%

Flutter滑动组件ListView和GirdView,源码浅读

ListView

inheritance 继承关系

Object > DiagnosticableTree > Widget > StatelessWidget > ScrollView > BoxScrollView > ListView

BoxScrollView

BoxScrollView 只有一个成员padding,根据滚动方向来添加padding,将另一方向的padding置为0。

BoxScrollView 需要传入的参数有很多,几乎多有传入参数均传给了其父类ScrollView

ScrollView

提供滚动(Scrollable)组件、viewport。Scrollable在滚动中回调函数viewportBuilder,提供给viewport偏移量,返回显示视图。

统一处理滚动过程中键盘处理——键盘失去焦点,通过FocusScope.of(context)获取当前焦点状态,调用unfocus方法房键盘消失。

ListView总结

在查看集成链路源码中,通过抽象方法划分功能模块。

  • ScrollView: 负责滚动相关功能

    • 集成Scrollable,实现滚动能力。通过集成Scrollable的返回的偏移量,管理自己的viewport。
    • 视口创建,Scrollable的回调方法viewportBuilder也很好的解耦了滚动功能和视口创建,视图功能交给使用者ScrollView, 由ScrollView的buildViewport方法实现。
    • 视图内容交给子类实现,在buildViewport方法中需要传入具体sliver,而sliver方法是ScrollView的抽象方法,交给子类实现(如BoxScrollView)
  • BoxScrollView: 负责处理滚动边距问题

    • 实现父类ScrollView的buildSlivers方法,处理边距问题
    • 具体sliver内容通过抽象方法buildChildLayout,交由子类实现
  • ListView: 实现buildChildLayout方法

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    @override
    Widget buildChildLayout(BuildContext context) {
    if (itemExtent != null) {
    return SliverFixedExtentList(
    delegate: childrenDelegate,
    itemExtent: itemExtent!,
    );
    } else if (prototypeItem != null) {
    return SliverPrototypeExtentList(
    delegate: childrenDelegate,
    prototypeItem: prototypeItem!,
    );
    }
    return SliverList(delegate: childrenDelegate);
    }

GirdView

inheritance

Object > DiagnosticableTree > Widget > StatelessWidget > ScrollView > BoxScrollView > GridView

GridView和ListView都是BoxScrollView子类。边距处理、滚动功能、视口创建均由父类实现。他们均需要实现buildChildLayout方法,去管理具体silver内容

GirdView

有两个成员girdDelegate和childrenDelegate,这两个类均默认在GirdView构造函数中创建。

  • girdDelegate成员是SliverGridDelegate类型,作用是管理sliver布局约束,SliverGridDelegate是抽象类,它有两个子类,一般我们使用也是使用这两个子类:
    • SliverGridDelegateWithFixedCrossAxisCount,通过交叉轴sliver个数
    • SliverGridDelegateWithMaxCrossAxisExtent, 通过sliver在交叉轴最大尺寸
  • childrenDelegate成员是SliverChildDelegate类型,girdView布局管理,给SliverGrid提供最大滚动距离。SliverChildDelegate也是抽象类,也是两个子类,一个用于有builder回调的,一个用于列表:
    • SliverChildBuilderDelegate
    • SliverChildListDelegate

实现buildChildLayout方法

1
2
3
4
5
6
7
@override
Widget buildChildLayout(BuildContext context) {
return SliverGrid(
delegate: childrenDelegate,
gridDelegate: gridDelegate,
);
}

GirdView总结

GirdView主要是通过两个成员变量来管理sliver布局和尺寸——childrenDelegate和gridDelegate,这两个成员的类型均是抽象类,也就是说我们完全可以通过集成相应抽象类,去具体实现我们想要的布局,让GirdView灵活性变得大很多。