最新公告
  • 欢迎您光临AA分享网,这里是高级程序员技术学习、分享的分享平台立即加入我们
  • LinearSnapHelper源码解析

    原文出处:Jameson's Blog 

    Google最新发布的support v4包更新到24.2.0,由原来的一个大包分割成多个小module。这次来聊聊RecyclerView的新特性和SnapHelper的关系。

    com.android.support:support-compat:24.2.0
    com.android.support:support-core-utils:24.2.0
    com.android.support:support-core-ui:24.2.0
    com.android.support:support-media-compat:24.2.0
    com.android.support:support-fragment:24.2.0

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

    SnapHelper.gif

    上面的效果只需下面几行代码即可。重点在于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;
    }

    代码下载

    https://github.com/huazhiyuan2008/RecyclerViewCardGallery

    AA分享网一个高级程序员的学习、分享的IT资源分享平台
    AA分享网-企业网站源码-PHP源码-网站模板-视频教程-IT技术教程 » LinearSnapHelper源码解析

    常见问题FAQ

    免费下载或者VIP会员专享资源能否直接商用?
    本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
    提示下载完但解压或打开不了?
    最常见的情况是下载不完整: 可对比下载完压缩包的与网盘上的容量,若小于网盘提示的容量则是这个原因。这是浏览器下载的bug,建议用百度网盘软件或迅雷下载。若排除这种情况,可在对应资源底部留言,或 联络我们.。
    找不到素材资源介绍文章里的示例图片?
    对于PPT,KEY,Mockups,APP,网页模版等类型的素材,文章内用于介绍的图片通常并不包含在对应可供下载素材包内。这些相关商业图片需另外购买,且本站不负责(也没有办法)找到出处。 同样地一些字体文件也是这种情况,但部分素材会在素材包内有一份字体下载链接清单。
    站壳网
    一个高级程序员模板开发平台

    发表评论

    • 74会员总数(位)
    • 2792资源总数(个)
    • 56本周发布(个)
    • 0 今日发布(个)
    • 237稳定运行(天)

    提供最优质的资源集合

    立即查看 了解详情