项目需要
使用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.EasySwipeMenuLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:contentView="@+id/content"
app:leftMenuView="@+id/left"
app:rightMenuView="@+id/right">
<LinearLayout
android: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">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="分享" />
</LinearLayout>
<LinearLayout
android:id="@+id/content"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#cccccc"
android:orientation="vertical"
android:padding="20dp">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="内容区域" />
</LinearLayout>
<LinearLayout
android:id="@+id/right"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@android:color/holo_red_light"
android:orientation="horizontal">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@android:color/holo_blue_bright"
android:padding="20dp"
android:text="删除" />
<TextView
android: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);
}
@Override
protected void convert(final BaseViewHolder helper, String item) {
helper.getView(R.id.right_menu_2).setOnClickListener(new View.OnClickListener() {
@Override
public 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() {
@Override
public 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() {
@Override
public void onClick(View v) {
Toast.makeText(MainActivity.this, "setOnClickListener", Toast.LENGTH_SHORT).show();
//在这个方法里面,因为此方法在【convert】里面,所以可以在这里获取到我们需要的position
int 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);
}
全部代码如下
@Override
public 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);
}
@Override
public 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);
}
这样就可以了,但是需要注意的是,如果这样设置了,我们的左右滑动就失效了,但是点击事件生效了。需要根据具体需求自行设置。