美文网首页Flutter圈子FlutterFlutter
Flutter - 分页滑动的ListView

Flutter - 分页滑动的ListView

作者: Ugly_K | 来源:发表于2019-12-05 12:13 被阅读0次

    2019/12/5 早

    Flutter - 分页滑动的ListView

    在类似图片查看的应用场景中,通常需要让ListView在滑动结束后停留在指定的分页位置,本篇就是使用Flutter ListView来实现这一需求

    1.思路

    • 创建一个ListView,且指定ScrollController:页面的移动停留都需要ScrollController来操作.
    • ListView的滑动进行监听:在ListView外部包裹一个Listener控件,同过其提供的api进行触摸监听.
    • 在滑动监听的同时,对触摸释放进行判断,并设置对应的事件。

    2.创建ListView

    创建一个基本的ListView,并对其设置指定的滑动方向(这很重要,因为后续的滑动计算和滑动方向是有着直接关联的),指定的ScrollController

    ScrollController _scrollController = new ScrollController();
    List<T> data = buildDefaultList();
    
    ListView.builder(
      physics: BouncingScrollPhysics(),
      controller: _scrollController,
      scrollDirection:Axis.horizontal,
      itemCount: data.length,
      itemBuilder: (BuildContext context, int index) {
        return buildImageItemView(index);
      },
    ),
    

    3.创建触摸监听部件Listener

    3.1 创建Listener:

    Offset pointerStart;
    Offset pointerEnd;
    
    Listener(
      onPointerDown: (event) {
        //保存触摸按下的位置信息
        pointerStart = event.position;
      },
      onPointerUp:  getPonitUpListenerInHorizontal()
      child: child,
    );
    

    这里举例仅仅使用横向正向滑动,所以我们只需要关心触摸按下事件与触摸离开事件,其实Listener也就提供了如下参数:

    const Listener({
      Key key,
      this.onPointerDown,//触摸按下
      this.onPointerMove,//触摸滑动
      this.onPointerUp,//触摸抬起
      this.onPointerCancel,//触摸取消
      this.behavior = HitTestBehavior.deferToChild,
      Widget child
    }) : assert(behavior != null),
         super(key: key, child: child);
    

    3.2实现触摸抬起监听

    onPointerUp的类型为PointerUpEventListener,暴露出一个PointerUpEvent,通过读取PointerUpEventposition来获取当前的位置,进而判断并执行需要处理的操作。

    代码如下:

    //获取屏幕宽度
    Size screenSize = MediaQuery.of(context).size;
    screenWidth = screenSize.width;
    
    /**
     * 构造横向滑动时候的触摸抬起监听
     */
    PointerUpEventListener getPonitUpListenerInHorizontal() {
      return (event) {
        pointerEnd = event.position;
        touchRangeX = pointerStart.dx - pointerEnd.dx;
        touchRangeY =pointerStart.dy - pointerEnd.dy;
        //所有的操作必须要满足滑动距离>10才算是滑动
        if (touchRangeX.abs() < 10) {
          nextOffset = screenWidth * lastPage;
          scrollAnimToOffset(_scrollController, nextOffset, () {
            if (lastPage < 0) {
              lastPage = 0;
            }
          });
          return;
        }
        //纵向操作大于横向操作三倍视为纵向操作
        //这个判断拦截只有在纵向操作距离大于20.0的时候才生效
        if (touchRangeX.abs() < touchRangeY.abs() && touchRangeY > 20) {
          nextOffset = screenWidth * lastPage;
          scrollAnimToOffset(_scrollController, nextOffset, () {
            if (lastPage < 0) {
              lastPage = 0;
            }
          });
          return;
        }
        
        //如果滑动小于当前屏幕1/8,那么就回弹复原,超过则移动到下一页
        //跳转到下一页或者上一页或者不动
        if (touchRangeX > screenWidth / 8) {
          nextOffset = screenWidth * (lastPage + 1);
                print("animate to ${nextOffset}");
          scrollAnimToOffset(_scrollController, nextOffset, () {
            lastPage++;
            if (lastPage >= _chapterDetail.data.length - 1) {
              lastPage = _chapterDetail.data.length - 1;
            }
          });
        } else if (touchRangeX < -1 * screenWidth / 8) {
          nextOffset = screenWidth * (lastPage - 1);
                print("animate to ${nextOffset}");
          scrollAnimToOffset(_scrollController, nextOffset, () {
            lastPage--;
            if (lastPage < 0) {
              lastPage = 0;
            }
          });
        } else {
          scrollAnimToOffset(_scrollController, screenWidth * lastPage, null);
        }
      };
    }
    

    列表滑动方法scrollAnimToOffset

    /**
     * 滑动到指定位置
     */
    void scrollAnimToOffset(ScrollController controller, double offset,
        void Function() onScrollCompleted) {
      controller
          .animateTo(offset,
              duration: Duration(
                milliseconds: 200,
              ),
              curve: Curves.easeIn)
          .then((v) {
        if (onScrollCompleted != null) {
          onScrollCompleted();
        }
      }).catchError((e) {
        print(e);
      });
    }
    

    4. 项目源码:go实现的爬虫服务器,Flutter进行前端展示,如果你觉得不错,给我一个Star吧!

    相关文章

      网友评论

        本文标题:Flutter - 分页滑动的ListView

        本文链接:https://www.haomeiwen.com/subject/vajdgctx.html