Android侧滑删除另一种实现,SwipeListView补充详解手机开发

前不久在在做聊天删除功能的时候使用SwipeListView进行侧滑删除有一点小问题,因为SwipeListView嵌套在Fragment内的时候,会报一个转换错误,原因是SwipeListView是基于ListView实现的SwipeListView
针对这个问题,首先想到的就是自定义View。首先看一下实现的效果。
这里写图片描述

自定义侧滑实现

实现的思路很简单,通过对onTouchEvent方法进行重写,判断滑动的距离来实现删除按钮的显示与隐藏。核心代码如下:

package com.shihui.butler.butler.msg.view; 
import android.content.Context; 
import android.content.res.TypedArray; 
import android.util.AttributeSet; 
import android.view.MotionEvent; 
import android.view.View; 
import android.view.ViewConfiguration; 
import android.widget.AdapterView; 
import android.widget.ListView; 
import android.widget.Scroller; 
import com.shihui.butler.R; 
public class SwipeListView extends ListView { 
public static int MODE_FORBID = 0; 
public static int MODE_RIGHT = 1; 
private int mode = MODE_FORBID; 
private int rightLength = 0; 
private int slidePosition; 
private int downY; 
private int downX; 
private View itemView; 
private Scroller scroller; 
private int mTouchSlop; 
private boolean canMove = false; 
private boolean isSlided = false; 
public SwipeListView(Context context) { 
this(context, null); 
} 
public SwipeListView(Context context, AttributeSet attrs) { 
this(context, attrs, 0); 
TypedArray a = context.obtainStyledAttributes(attrs, 
R.styleable.SlideMode); 
mode = a.getInt(R.styleable.SlideMode_mode, 0); 
} 
public SwipeListView(Context context, AttributeSet attrs, int defStyle) { 
super(context, attrs, defStyle); 
TypedArray a = context.obtainStyledAttributes(attrs, 
R.styleable.SlideMode); 
mode = a.getInt(R.styleable.SlideMode_mode, 0); 
scroller = new Scroller(context); 
mTouchSlop = ViewConfiguration.get(getContext()).getScaledTouchSlop(); 
} 
@Override 
public boolean onTouchEvent(MotionEvent ev) { 
final int action = ev.getAction(); 
int lastX = (int) ev.getX(); 
switch (action) { 
case MotionEvent.ACTION_DOWN: 
System.out.println("touch-->" + "down"); 
if (this.mode == MODE_FORBID) { 
return super.onTouchEvent(ev); 
} 
if (isSlided) { 
scrollBack(); 
return false; 
} 
if (!scroller.isFinished()) { 
return false; 
} 
downX = (int) ev.getX(); 
downY = (int) ev.getY(); 
slidePosition = pointToPosition(downX, downY); 
if (slidePosition == AdapterView.INVALID_POSITION) { 
return super.onTouchEvent(ev); 
} 
itemView = getChildAt(slidePosition - getFirstVisiblePosition()); 
if (this.mode == MODE_RIGHT) { 
this.rightLength = -itemView.getPaddingRight(); 
} 
break; 
case MotionEvent.ACTION_MOVE: 
System.out.println("touch-->" + "move"); 
if (!canMove 
&& slidePosition != AdapterView.INVALID_POSITION 
&& (Math.abs(ev.getX() - downX) > mTouchSlop && Math.abs(ev 
.getY() - downY) < mTouchSlop)) { 
int offsetX = downX - lastX; 
if (offsetX > 0 && this.mode == MODE_RIGHT) { 
canMove = true; 
} else { 
canMove = false; 
} 
MotionEvent cancelEvent = MotionEvent.obtain(ev); 
cancelEvent 
.setAction(MotionEvent.ACTION_CANCEL 
| (ev.getActionIndex() << MotionEvent.ACTION_POINTER_INDEX_SHIFT)); 
onTouchEvent(cancelEvent); 
} 
if (canMove) { 
requestDisallowInterceptTouchEvent(true); 
int deltaX = downX - lastX; 
if (deltaX > 0 && this.mode == MODE_RIGHT) { 
itemView.scrollTo(deltaX, 0); 
} else { 
itemView.scrollTo(0, 0); 
} 
return true; 
} 
case MotionEvent.ACTION_UP: 
System.out.println("touch-->" + "up"); 
if (canMove) { 
canMove = false; 
scrollByDistanceX(); 
} 
break; 
} 
return super.onTouchEvent(ev); 
} 
private void scrollByDistanceX() { 
if (this.mode == MODE_FORBID) { 
return; 
} 
if (itemView.getScrollX() > 0 && this.mode == MODE_RIGHT) { 
if (itemView.getScrollX() >= rightLength / 2) { 
scrollLeft(); 
} else { 
scrollBack(); 
} 
} else { 
scrollBack(); 
} 
} 
private void scrollLeft() { 
isSlided = true; 
final int delta = (rightLength - itemView.getScrollX()); 
scroller.startScroll(itemView.getScrollX(), 0, delta, 0, 
Math.abs(delta)); 
postInvalidate(); // 刷新itemView 
} 
private void scrollBack() { 
isSlided = false; 
scroller.startScroll(itemView.getScrollX(), 0, -itemView.getScrollX(), 
0, Math.abs(itemView.getScrollX())); 
// 刷新itemView 
postInvalidate(); 
} 
@Override 
public void computeScroll() { 
if (scroller.computeScrollOffset()) { 
itemView.scrollTo(scroller.getCurrX(), scroller.getCurrY()); 
postInvalidate(); 
} 
} 
public void slideBack() { 
this.scrollBack(); 
} 
} 

然后我们在界面上引入上面的SwipeListView。

<SwipeListView 
            android:id="@+id/msg_listView" 
android:layout_width="match_parent" 
android:layout_height="match_parent" 
android:animationCache="false" 
android:divider="#E4E4E4" 
android:dividerHeight="0.5px" 
android:scrollbars="none" 
android:scrollingCache="false" 
app:mode="right"/>

在Adapter的子布局中,通过对SwipeListView滑动监听即可。
下面是Adapter的子布局方面,相关代码:

<LinearLayout 
xmlns:android="http://schemas.android.com/apk/res/android" 
xmlns:app="http://schemas.android.com/apk/res-auto" 
android:layout_width="match_parent" 
android:layout_height="wrap_content" 
android:orientation="horizontal" 
android:background="@color/white" 
android:paddingRight="-100dp" 
> 
//...省略部分代码 
android:background="@android:color/holo_red_light" 
android:gravity="center" 
android:text="删除" 
android:textColor="@android:color/white" 
android:textSize="18sp" /> 
</LinearLayout> 

为了实现点击删除按钮删除,我们需要在Adapter中给按钮绑定点击事件,并通过接口回传给页面进行刷新。
adapter代码

private void initItemClick(ViewHolder viewHolder, final int position) { 
viewHolder.itemDel.setOnClickListener(new View.OnClickListener() { 
@Override 
public void onClick(View view) { 
if (mRemoveListener != null) 
mRemoveListener.onRemoveItem(position); 
} 
}); 
} 
//声明接口监听 
public void setRemoveListener(OnRemoveListener removeListener) { 
this.mRemoveListener = removeListener; 
} 
public interface OnRemoveListener { 
void onRemoveItem(int position); 
}

然后我们在Fragment中直接调用即可。

 controller.getAdapter().setRemoveListener(new MsgAdapter.OnRemoveListener() { 
@Override 
public void onRemoveItem(int position) { 
//删除聊天逻辑 
} 
});

就写到这里吧,有任何问题欢迎留言。

原创文章,作者:奋斗,如若转载,请注明出处:https://blog.ytso.com/5658.html

(0)
上一篇 2021年7月17日
下一篇 2021年7月17日

相关推荐

发表回复

登录后才能评论