为了账号安全,请及时绑定邮箱和手机立即绑定

LinearSnapHelper源码解析

标签:
Android

Google最新发布的support recyclerview包更新到24.2.0,这次来聊聊RecyclerView的新特性和SnapHelper的关系。

一句话介绍SnapHelper: SnapHelper是RecyclerView功能的一种拓展,使RecyclerView滑动行为类似ViewPager,无论怎么滑动最终停留在某页正中间。ViewPager一次只能滑动一页,RecyclerView+SnapHelper方式可以一次滑动好几页,且最终都停留在某页正中间。非常实用和酷炫。
SnapHelper的实现原理是监听RecyclerView.OnFlingListener中的onFling接口。LinearSnapHelper是抽象类SnapHelper的具体实现。

上面的效果只需下面几行代码即可。重点在于new LinearSnapHelper().attachToRecyclerView(recyclerView);

LinearLayoutManager linearLayoutManager = new LinearLayoutManager(getContext(), LinearLayoutManager.HORIZONTAL, false);
recyclerView.setLayoutManager(linearLayoutManager);

new LinearSnapHelper().attachToRecyclerView(recyclerView);

接下来具体分析LinearSnapHelper是怎么实现类似ViewPager的功能的

attachToRecyclerView,居中处理分析

public void attachToRecyclerView(@Nullable RecyclerView recyclerView) throws IllegalStateException {

   ...

   snapToTargetExistingView();

   ...

}

/**

 * 1. 找到居中显示的View

 * 2. 计算view离当前的位置距离, 调用mRecyclerView.smoothScrollBy使其居中

 */

private void snapToTargetExistingView() {

    View snapView = findSnapView(layoutManager);

    int[] snapDistance = calculateDistanceToFinalSnap(layoutManager, snapView);

    if (snapDistance[0] != 0 || snapDistance[1] != 0) {

        mRecyclerView.smoothScrollBy(snapDistance[0], snapDistance[1]);

    }

}

/**

 * 1. 找到当前RecyclerView的居中位置center

 * 2. 循环遍历子节点,找出子节点居中位置最接近center的视图,及SnapView

 */

public View findSnapView(RecyclerView.LayoutManager layoutManager) {

    ...

}

/**

 * 计算到targetView要移动的距离

 */

@Override

public int[] calculateDistanceToFinalSnap(

        @NonNull RecyclerView.LayoutManager layoutManager, @NonNull View targetView) {

      ... 

}

RecyclerView.OnFling,滑动后停止到居中位置分析

SnapHelper extends RecyclerView.OnFlingListener,重载onFling函数

public boolean onFling(int velocityX, int velocityY) {

    LayoutManager layoutManager = mRecyclerView.getLayoutManager();

    if (layoutManager == null) {

        return false;

    }

    RecyclerView.Adapter adapter = mRecyclerView.getAdapter();

    if (adapter == null) {

        return false;

    }

    int minFlingVelocity = mRecyclerView.getMinFlingVelocity();

    return (Math.abs(velocityY) > minFlingVelocity || Math.abs(velocityX) > minFlingVelocity)

            && snapFromFling(layoutManager, velocityX, velocityY);

}

/**

 * 同样的套路,先根据移动速度确定最终位置,然后startSmoothScroll

 */

private boolean snapFromFling(@NonNull LayoutManager layoutManager, int velocityX,

        int velocityY) {

    ...

    int targetPosition = findTargetSnapPosition(layoutManager, velocityX, velocityY);

    if (targetPosition == RecyclerView.NO_POSITION) {

        return false;

    }

    smoothScroller.setTargetPosition(targetPosition);

    layoutManager.startSmoothScroll(smoothScroller);

    return true;

}

原文链接:http://www.apkbus.com/blog-705730-62431.html

点击查看更多内容
TA 点赞

若觉得本文不错,就分享一下吧!

评论

作者其他优质文章

正在加载中
  • 推荐
  • 评论
  • 收藏
  • 共同学习,写下你的评论
感谢您的支持,我会继续努力的~
扫码打赏,你说多少就多少
赞赏金额会直接到老师账户
支付方式
打开微信扫一扫,即可进行扫码打赏哦
今天注册有机会得

100积分直接送

付费专栏免费学

大额优惠券免费领

立即参与 放弃机会
微信客服

购课补贴
联系客服咨询优惠详情

帮助反馈 APP下载

慕课网APP
您的移动学习伙伴

公众号

扫描二维码
关注慕课网微信公众号

举报

0/150
提交
取消