自定义SnapHelper系列二,实现居左和居右

在上篇文章中,我们对SnapHelper源码进行了分析。接下来我们来实现能居左和居右的SnapHeler。我们先创建一个类CustomSnapHelper继承SnapHelper。并把LinearSnapHelpe中里的代码全部复制过来。然后根据上篇的内容,可以如果要居左显示item的话。要修该

  @Nullable
    private View findCenterView(LayoutManager layoutManager, OrientationHelper helper) {
        int childCount = layoutManager.getChildCount();
        if (childCount == 0) {
            return null;
        } else {
            View closestChild = null;
            int center;
            if (layoutManager.getClipToPadding()) {
               //  center = helper.getStartAfterPadding() + helper.getTotalSpace() / 2;//居中 注释掉,
                center = helper.getStartAfterPadding() + helper.getDecoratedMeasurement(layoutManager.getChildAt(0)) / 2;//居左 center这时是左边item完全显示时的中心
            } else {
                center = helper.getEnd() / 2;
            }

            int absClosest = 2147483647;
            for (int i = 0; i < childCount; ++i) {
                View child = layoutManager.getChildAt(i);
                int childCenter = helper.getDecoratedStart(child) + helper.getDecoratedMeasurement(child) / 2;
                int absDistance = Math.abs(childCenter - center);
                if (absDistance < absClosest) {
                    absClosest = absDistance;
                    closestChild = child;
                }
            }

            return closestChild;
        }
    }

我们把center = helper.getStartAfterPadding() + helper.getTotalSpace() / 2改成 center = helper.getStartAfterPadding() + helper.getDecoratedMeasurement(layoutManager.getChildAt(0)) / 2。拿到左边居中的中心位置。下面的for()逻辑不变。这样我们拿到目标View之后,就可以进行calculateDistanceToFinalSnap()方法来算出距离了。我们只有修改里面的distanceToCenter()方法就可以

  private int distanceToCenter(@NonNull LayoutManager layoutManager, @NonNull View targetView, OrientationHelper helper) {
        int childCenter = helper.getDecoratedStart(targetView) + helper.getDecoratedMeasurement(targetView) / 2;
        int containerCenter;
        if (layoutManager.getClipToPadding()) {
            //containerCenter = helper.getStartAfterPadding() + helper.getTotalSpace() / 2;  //居中
             containerCenter = helper.getStartAfterPadding() + helper.getDecoratedMeasurement(targetView) / 2;//居左
        } else {
            containerCenter = helper.getEnd() / 2;
        }

        return childCenter - containerCenter;
    }

这样就可以实现居左功能了,效果图如下:
在这里插入图片描述
但是这时候我们把item的大小改一下。在一些情况会出现下面的效果:
在这里插入图片描述
我们会发现最右边的item不能完全显示。这个是因为在能可见的getCount()里,第一个item要比第二个item的位置距离左边居中的位置近,所以会滑向第一个,这样最后一个有滚动回去了。我们只有在上面的findCenterView()方法中加个判断。

  @Nullable
    private View findCenterView(LayoutManager layoutManager, OrientationHelper helper) {
        int childCount = layoutManager.getChildCount();
        if (childCount == 0) {
            return null;
        } else {
            View closestChild = null;
            int center;
            if (layoutManager.getClipToPadding()) {
               //  center = helper.getStartAfterPadding() + helper.getTotalSpace() / 2;//居中 注释掉,
                center = helper.getStartAfterPadding() + helper.getDecoratedMeasurement(layoutManager.getChildAt(0)) / 2;//居左 center这时是左边item完全显示时的中心
            } else {
                center = helper.getEnd() / 2;
            }
       
 			 View viewRight = layoutManager.getChildAt(childCount - 1);
            int LastPos = layoutManager.getPosition(viewRight);
                 //获得position,判断是否是最后一个
            if (LastPos == layoutManager.getItemCount() - 1) {
                //居左时要判断 最右一个item        
                if (helper.getDecoratedEnd(viewRight) ==helper.getEndAfterPadding()) {
                    return  viewRight;
                }
            }


            int absClosest = 2147483647;
            for (int i = 0; i < childCount; ++i) {
                View child = layoutManager.getChildAt(i);
                int childCenter = helper.getDecoratedStart(child) + helper.getDecoratedMeasurement(child) / 2;
                int absDistance = Math.abs(childCenter - center);
                if (absDistance < absClosest) {
                    absClosest = absDistance;
                    closestChild = child;
                }
            }

            return closestChild;
        }
    }

这样就可以了,效果图如下:
在这里插入图片描述
同样对于居右而已。只要把上面的findCenterView()方法中的center改成 center = helper.getStartAfterPadding() + helper.getTotalSpace() - helper.getDecoratedMeasurement(layoutManager.getChildAt(0)) / 2;和distanceToCenter()方法中的containerCenter 改成containerCenter = helper.getStartAfterPadding() + helper.getTotalSpace() - helper.getDecoratedMeasurement(targetView) / 2;同样的居右时要对最左进行判断,在findCenterView()中:

		 View viewLeft = layoutManager.getChildAt(0);
            int frisPos = layoutManager.getPosition(viewLeft);
            if (frisPos == 0) {
                //居右时, 最右一个item
              if (helper.getDecoratedStart(viewLeft)==helper.getStartAfterPadding())
              {
                  return viewLeft;
              }
            }

最终居右效果图如下。
在这里插入图片描述

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值