recyclerview 實現viewpager grideview分頁效果 GrideSnapHelper
阿新 • • 發佈:2019-01-29
為了逼自己學習,所以瞎折騰一下,讓自己張點見識。
專案中原來使用的是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小的錨點