网格整页滑动"/>
RecycleView实现网格整页滑动
需求分析
这篇博客写作来源是项目需求
产品经理说:用六宫格展示一页数据,用户左滑/右滑的时候,要整页滑动的效果。
解释这句话的意思就是:
(1)一页只能展示6条数据;
(2)只支持横向滑动,用户只能一页一页的滑(相当于用户一次要滑动6条数据);
(3)用户左滑是向前翻页,右上角页码随之变换;
(4)用户右滑是向后翻页,右上角页码随之变换;
(5)点击单条数据,可以跳转这道菜的详情页面。
以下是产品原型图:
我在github上逛了挺久的,就是找不到贴合我们实际项目需求的控件。我认为这个功能类似于下拉刷新和上拉加载更多,所不同的是,首先,这个不是垂直方向的,其次,滑动的话只能按照页面滑,一次变更6条数据。
既然如此,只好自己动手动脑来实现了。
我的想法其实很简单粗暴,就是自己监听用户是向左滑还是右滑还是在点击item,之后做不同的滑动和点击事件处理。这个方法一开始没有想到,试了其他方案都不成功,最后被逼出的这个。这也说明,项目需求有时候不会一眼就做出来的时候,多试试其他方案,试的过程中,想法也就出来了。
实现:
采用recycleview + gridlayoutmanager,在recycleview中监听用户的触摸事件,核心代码如下:
注意:当用户滑动的时候,我们自己处理此事件;但是如果是用户点击item的话,就继续交回给父控件自己处理,因为recycleview本身就是支持点击事件的,所以之前返回什么值,就返回什么值,不做改变就好。
但是遗留了一个问题:就是滑动之后,再点击,第一次不响应这个点击,之后开始响应点击事件了。
希望能有人帮忙解答。
public class MyRecycleView extends RecyclerView {private long startTime;private float mTouchStartX;private int pressX;public static final String TAG = "MyRecycleView";private MyScrollListener mMyScrollListener;public void setMyScrollListener(MyScrollListener myScrollListener) {mMyScrollListener = myScrollListener;}public MyRecycleView(@NonNull Context context) {super(context);}public MyRecycleView(@NonNull Context context, @Nullable AttributeSet attrs) {super(context, attrs);}public MyRecycleView(@NonNull Context context, @Nullable AttributeSet attrs, int defStyle) {super(context, attrs, defStyle);}@Overridepublic boolean onTouchEvent(MotionEvent event) {int action = event.getAction();switch (action) {case MotionEvent.ACTION_DOWN:startTime = System.currentTimeMillis();mTouchStartX = event.getX();pressX = (int) event.getRawX();Log.d(TAG,"mTouchStartX = "+mTouchStartX);Log.d(TAG,"pressX = "+pressX);break;case MotionEvent.ACTION_MOVE:float mMoveStartX = event.getX();int deltaX = (int) (mMoveStartX - mTouchStartX);Log.d(TAG,"deltaX = "+deltaX);break;case MotionEvent.ACTION_UP:int tempDX = (int) event.getRawX() - pressX;mTouchStartX = event.getX();Log.d(TAG,"tempDX = "+tempDX);if(tempDX<=6&&tempDX>=-6){long endTime = System.currentTimeMillis();if ((endTime - startTime) < 2 * 1000L) {//设置点击事件:Log.d(TAG,"点击事件 ");return super.onTouchEvent(event);}}else if(tempDX>6){//6这个值没有什么实际意义,只是认为差不多这个值就可以做滑动和点击的区分if(mMyScrollListener!=null){Log.d(TAG,"onRefresh ");mMyScrollListener.onRefresh();}}else if(tempDX<-6){if(mMyScrollListener!=null){Log.d(TAG,"onLoadMore ");mMyScrollListener.onLoadMore();}}break;}return true;}public interface MyScrollListener {void onLoadMore();void onRefresh();}}
使用:
和原本recycleview的使用保持不变,只不过要实现自己定义的两个接口:
rvRecipe.setMyScrollListener(this);//加载之后/之前页面数据
mRecipeListAdapter.setOnItemClickListener(this);//点击事件@Overridepublic void onLoadMore() {Log.d(TAG,"加载更多");mPresenter.fetchRecipesData();}@Overridepublic void onRefresh() {Log.d(TAG,"获取之前页面的数据");mPresenter.fetchPreviousRecipesData();}
其实还有一个问题:就是采用这样的方案,用户滑动的时候,虽然用户能感知到一次性6条数据做了变更,这给人感觉好像页面整体都滑动了,但实际上这个控件是没有任何滑动效果的。
最终效果图就是这个样子了:
更多推荐
RecycleView实现网格整页滑动
发布评论