项目需要
使用Recyclerview进行列表的数据加载的时候,需要对这个Item进行左右滑动进行操作的功能,
比如这样
需求实现
上面图来源于
https://github.com/anzaizai/EasySwipeMenuLayout
这是一个可以用来进行列表左滑、右滑的项目,可以集成到自己的项目中
compile 'com.github.anzaizai:EasySwipeMenuLayout:1.1.4'
推荐搭配Brvah框架使用
api 'com.github.CymChad:BaseRecyclerViewAdapterHelper:2.9.49'
使用方式业非常简单
例如
<com.guanaj.easyswipemenulibrary.EasySwipeMenuLayoutandroid:layout_width="match_parent"android:layout_height="wrap_content"app:contentView="@+id/content"app:leftMenuView="@+id/left"app:rightMenuView="@+id/right"><LinearLayoutandroid:id="@+id/left"android:layout_width="100dp"android:layout_height="wrap_content"android:background="@android:color/holo_blue_dark"android:orientation="horizontal"android:padding="20dp"><TextViewandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:text="分享" /></LinearLayout><LinearLayoutandroid:id="@+id/content"android:layout_width="match_parent"android:layout_height="wrap_content"android:background="#cccccc"android:orientation="vertical"android:padding="20dp"><TextViewandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:text="内容区域" /></LinearLayout><LinearLayoutandroid:id="@+id/right"android:layout_width="wrap_content"android:layout_height="wrap_content"android:background="@android:color/holo_red_light"android:orientation="horizontal"><TextViewandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:background="@android:color/holo_blue_bright"android:padding="20dp"android:text="删除" /><TextViewandroid:id="@+id/right_menu_2"android:layout_width="wrap_content"android:layout_height="wrap_content"android:background="@android:color/holo_orange_dark"android:padding="20dp"android:text="收藏" /></LinearLayout></com.guanaj.easyswipemenulibrary.EasySwipeMenuLayout>
public class MyAdapter extends BaseQuickAdapter<String, BaseViewHolder> {public MyAdapter(@LayoutRes int layoutResId, @Nullable List<String> data) {super(layoutResId, data);}@Overrideprotected void convert(final BaseViewHolder helper, String item) {helper.getView(R.id.right_menu_2).setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View v) {Toast.makeText(MainActivity.this, "收藏", Toast.LENGTH_SHORT).show();EasySwipeMenuLayout easySwipeMenuLayout = helper.getView(R.id.es);easySwipeMenuLayout.resetStatus();}});helper.getView(R.id.content).setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View v) {Toast.makeText(MainActivity.this, "setOnClickListener", Toast.LENGTH_SHORT).show();}});}}
按照这个Demo上面讲的,这样基本上就可以了,但是有问题需要注意:
使用这个框架之后,虽然实现了左右滑动显示不用的按钮的效果,但是这个整个Item的点击事件是被拦截了,这就导致
// rvAdapter.setOnItemClickListener(new BaseQuickAdapter.OnItemClickListener() {
// @Override
// public void onItemClick(BaseQuickAdapter adapter, View view, int position) {
//
// }
// });
这个方法是失效的,要是对这个没有什么需求的话这个可以不用管,但是我们要是对某一个Item进行操作的时候,怎么获得这个position呢?
需要这样做
helper.getView(R.id.content).setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View v) {Toast.makeText(MainActivity.this, "setOnClickListener", Toast.LENGTH_SHORT).show();
//在这个方法里面,因为此方法在【convert】里面,所以可以在这里获取到我们需要的positionint pos = helper.getAdapterPosition();//这样就可以操作了}});
但是有时候我们的页面要复用,需要这个点击事件的时候,这个时候该怎么办呢,这个时候就要修改这个代码了,修改的地方不多
首先我们需要在github上面把这个项目下载下来,把里面的代码放到我们项目中,代码很少,我们在这个【EasySwipeMenuLayout】里面
加入一个字段
private boolean isNeedClick = false; //是否需要(非滑动之后的)点击事件
public boolean isNeedClick() {return isNeedClick;}public void setNeedClick(boolean needClick) {isNeedClick = needClick;}
然后在里面的【dispatchTouchEvent】和【onInterceptTouchEvent】方法里面加入
if (isNeedClick()) {return super.dispatchTouchEvent(ev);}
和
if (isNeedClick()) {return super.onInterceptTouchEvent(event);}
全部代码如下
@Overridepublic boolean dispatchTouchEvent(MotionEvent ev) {if (isNeedClick()) {return super.dispatchTouchEvent(ev);}switch (ev.getAction()) {case MotionEvent.ACTION_DOWN: {// System.out.println(">>>>dispatchTouchEvent() ACTION_DOWN");isSwipeing = false;if (mLastP == null) {mLastP = new PointF();}mLastP.set(ev.getRawX(), ev.getRawY());if (mFirstP == null) {mFirstP = new PointF();}mFirstP.set(ev.getRawX(), ev.getRawY());if (mViewCache != null) {if (mViewCache != this) {mViewCache.handlerSwipeMenu(State.CLOSE);}// Log.i(TAG, ">>>有菜单被打开");getParent().requestDisallowInterceptTouchEvent(true);}break;}case MotionEvent.ACTION_MOVE: {// System.out.println(">>>>dispatchTouchEvent() ACTION_MOVE getScrollX:" + getScrollX());float distanceX = mLastP.x - ev.getRawX();float distanceY = mLastP.y - ev.getRawY();if (Math.abs(distanceY) > mScaledTouchSlop && Math.abs(distanceY) > Math.abs(distanceX)) {break;}
// if (Math.abs(distanceX) <= mScaledTouchSlop){
// break;
// }// Log.i(TAG, ">>>>>distanceX:" + distanceX);scrollBy((int) (distanceX), 0);//滑动使用scrollBy//越界修正if (getScrollX() < 0) {if (!mCanRightSwipe || mLeftView == null) {scrollTo(0, 0);} else {//左滑if (getScrollX() < mLeftView.getLeft()) {scrollTo(mLeftView.getLeft(), 0);}}} else if (getScrollX() > 0) {if (!mCanLeftSwipe || mRightView == null) {scrollTo(0, 0);} else {if (getScrollX() > mRightView.getRight() - mContentView.getRight() - mContentViewLp.rightMargin) {scrollTo(mRightView.getRight() - mContentView.getRight() - mContentViewLp.rightMargin, 0);}}}//当处于水平滑动时,禁止父类拦截if (Math.abs(distanceX) > mScaledTouchSlop
// || Math.abs(getScrollX()) > mScaledTouchSlop) {// Log.i(TAG, ">>>>当处于水平滑动时,禁止父类拦截 true");getParent().requestDisallowInterceptTouchEvent(true);}mLastP.set(ev.getRawX(), ev.getRawY());break;}case MotionEvent.ACTION_UP:case MotionEvent.ACTION_CANCEL: {// System.out.println(">>>>dispatchTouchEvent() ACTION_CANCEL OR ACTION_UP");finalyDistanceX = mFirstP.x - ev.getRawX();if (Math.abs(finalyDistanceX) > mScaledTouchSlop) {// System.out.println(">>>>P");isSwipeing = true;}result = isShouldOpen(getScrollX());handlerSwipeMenu(result);break;}default: {break;}}return super.dispatchTouchEvent(ev);}
@Overridepublic boolean onInterceptTouchEvent(MotionEvent event) {if (isNeedClick()) {return super.onInterceptTouchEvent(event);}// Log.d(TAG, "<<<<dispatchTouchEvent() called with: " + "ev = [" + event + "]");switch (event.getAction()) {case MotionEvent.ACTION_DOWN: {break;}case MotionEvent.ACTION_MOVE: {//滑动时拦截点击时间if (Math.abs(finalyDistanceX) > mScaledTouchSlop) {// 当手指拖动值大于mScaledTouchSlop值时,认为应该进行滚动,拦截子控件的事件// Log.i(TAG, "<<<onInterceptTouchEvent true");return true;}
// if (Math.abs(finalyDistanceX) > mScaledTouchSlop || Math.abs(getScrollX()) > mScaledTouchSlop) {
// Log.d(TAG, "onInterceptTouchEvent: 2");
// return true;
// }break;}case MotionEvent.ACTION_UP:case MotionEvent.ACTION_CANCEL: {//滑动后不触发contentView的点击事件if (isSwipeing) {isSwipeing = false;finalyDistanceX = 0;return true;}}}return super.onInterceptTouchEvent(event);}
然后我们在Adapter里面
if (helper.getView(R.id.easy_swipe_ly) instanceof EasySwipeMenuLayout) {((EasySwipeMenuLayout) helper.getView(R.id.easy_swipe_ly)).setNeedClick(true);}
这样就可以了,但是需要注意的是,如果这样设置了,我们的左右滑动就失效了,但是点击事件生效了。需要根据具体需求自行设置。