为了逼自己学习,所以瞎折腾一下,让自己张点见识。
项目中原来使用的是ViewPager + GrideView 实现的卡片滑动,代码挺多的,我非得想改造成用recyclerView实现,
话说折腾成功。先看下效果。
每页三列,滑动停止后自动找到最近的一页停下。
大多数人都是直接实现SnapHelper,但是我武功没那么高强,况且只要能解决问题的同志就是好裁缝!对于那些没有问题制造困难也要解决问题的好同志,我只能说,带我飞.
我给这个类起名叫GrideSnapHelper,感觉实现了GrideSnapHelper很高达上...其实我只实现了滚动监听而已.
使用方法:
GrideSnapHelper grideSnapHelper = new GrideSnapHelper(3,3,this); grideSnapHelper.attachToRecycleView(recyclerView);
GrideSnapHelper源码
import android.app.Activity; import android.support.v7.widget.GridLayoutManager; import android.support.v7.widget.RecyclerView; import android.util.Log; import android.view.View; import android.view.WindowManager; import java.util.ArrayList; import static android.content.ContentValues.TAG; import static android.support.v7.widget.RecyclerView.SCROLL_STATE_DRAGGING; import static android.support.v7.widget.RecyclerView.SCROLL_STATE_SETTLING; import static android.widget.NumberPicker.OnScrollListener.SCROLL_STATE_IDLE; /** * Created by 瑜哥 on 2018/3/29. * 1:寻找锚点:visiable fist last范围内%行*列=0的都是锚点 * 2:锚点为正,如果超过屏幕的一半,取当前锚点-1,如果小于屏幕一半取当前锚点 */ public class GrideSnapHelper { RecyclerView recyclerView; int horizon, column; private GridLayoutManager layoutManager; private ArrayList<Integer> positionLisit; private final int screen_width; public GrideSnapHelper(int horizon, int column, Activity ctx) { this.horizon = horizon; this.column = column; WindowManager wm1 = ctx.getWindowManager(); screen_width = wm1.getDefaultDisplay().getWidth(); } public void attachToRecycleView(RecyclerView recyclerView) { this.recyclerView = recyclerView; setListener(); } private void setListener() { if (recyclerView == null) { return; } recyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() { @Override public void onScrollStateChanged(RecyclerView recyclerView, int newState) { super.onScrollStateChanged(recyclerView, newState); switch (newState) { case SCROLL_STATE_IDLE: System.out.println("recyclerview已经停止滚动"); snapView(); break; case SCROLL_STATE_DRAGGING: System.out.println("recyclerview正在被拖拽"); break; case SCROLL_STATE_SETTLING: System.out.println("recyclerview正在依靠惯性滚动"); break; } } }); } private void snapView() { if (layoutManager ==null) { layoutManager = (GridLayoutManager)recyclerView.getLayoutManager(); positionLisit = new ArrayList<>(); } //寻找锚点 positionLisit.clear(); int firstVisibleItem = layoutManager.findFirstVisibleItemPosition(); int lastVisibleItem = layoutManager.findLastVisibleItemPosition(); for (int i = firstVisibleItem;i<=lastVisibleItem;i++) { if (i%(column*horizon)==0) positionLisit.add(i); } Log.d(TAG, "positionLisit: "+positionLisit.toString()); //选择锚点 int targetPosition = 0; //有1个锚点 锚点X坐标大于屏幕一半取上一个锚点,锚点X坐标小于屏幕一半取当前锚点 if (positionLisit.size() == 1) { View item = layoutManager.findViewByPosition(positionLisit.get(0)); if (item==null) return; final int []location=new int[2]; item.getLocationOnScreen(location); int x=location[0];//获取当前位置的横坐标 int y=location[1];//获取当前位置的纵坐标 if (x > screen_width / 2) { targetPosition = positionLisit.get(0) - column * horizon; } else { targetPosition = positionLisit.get(0); } } //有2个锚点 取小锚点 else if (positionLisit.size() == 2) { targetPosition = positionLisit.get(0); } Log.d(TAG, "targetPosition: "+targetPosition); // recyclerView.smoothScrollToPosition(targetPosition); layoutManager.scrollToPositionWithOffset(targetPosition, 0); } }
其实代码码只有两句话:
1:寻找锚点:可视范围内所有条目的Position%(每页条目数)=0的都是锚点
2:选择锚点:有1个锚点 锚点X坐标大于屏幕一半取上一个锚点(当前锚点-每页条目数),锚点X坐标小于屏幕一半取当前锚点
有2个锚点 取position小的锚点