自己通过用Android自带的ViewDragHelper这个类写了一个滑动删除 ,一开始在还没写删除逻辑的时候,都是正常运作,加了删除逻辑之后,数据是删除了,但是整个页面无法滑动也无法点击,但是Log没有报错误...这让我很郁闷,一开始以为是滑动冲突的问题,可是我把删除逻辑全注释了,就打印点击删除的Log,发现又能正常运用,这让我很无语.... 有没有大佬帮小弟解答...
package com.example.bilibili_qq50;
import android.content.Context;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.FrameLayout;
import android.widget.TextView;
import android.widget.Toast;
import androidx.annotation.NonNull;
import androidx.customview.widget.ViewDragHelper;
//滑动删除
public class SwipeLayout extends FrameLayout implements View.OnClickListener {
private static final String TAG = "SwipeLayout";
private ViewDragHelper mHelper;
private View mDeleteView;
private View mContentView;
private int mContentWidth;
private int mContentHeight;
private int mDeleteWidth;
private onSwipeClickListener mOnSwipeClickListener;
private float mDownX;
private float mDownY;
private SwipeManager mManager;
private enum SwipeState{
OPEN,CLOSE;
}
private SwipeState currentStat=SwipeState.CLOSE;//默认关闭
public SwipeLayout(Context context) {
this(context,null);
}
public SwipeLayout(Context context, AttributeSet attrs) {
this(context, attrs,0);
}
public SwipeLayout(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
initViewHelper(context);
mManager = SwipeManager.getManager();
}
private void initViewHelper(Context context) {
mHelper = ViewDragHelper.create(this,mCallback);
}
@Override
protected void onFinishInflate() {
super.onFinishInflate();
mContentView = getChildAt(0);
mDeleteView = getChildAt(1);
TextView btnTop = mDeleteView.findViewById(R.id.swipe_top);
TextView btnDelete = mDeleteView.findViewById(R.id.swipe_delete);
btnTop.setOnClickListener(this);
btnDelete.setOnClickListener(this);
}
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
mContentHeight = mContentView.getMeasuredHeight();
mContentWidth = mContentView.getMeasuredWidth();
mDeleteWidth = mDeleteView.getMeasuredWidth();
Log.d(TAG,"mContentHeight --> "+mContentHeight );
Log.d(TAG, "mContentWidth: "+mContentWidth);
}
@Override
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
//先摆放内容
mContentView.layout(0,0,mContentWidth,mContentHeight);
//摆放删除
mDeleteView.layout(mContentView.getRight(),0,mContentView.getRight()+mDeleteWidth,mContentHeight);
}
private ViewDragHelper.Callback mCallback=new ViewDragHelper.Callback() {
@Override
public boolean tryCaptureView(@NonNull View child, int pointerId) {
return child==mContentView || child==mDeleteView;
}
@Override
public void onViewPositionChanged(@NonNull View changedView, int left, int top, int dx, int dy) {
super.onViewPositionChanged(changedView, left, top, dx, dy);
if (changedView==mContentView){
mDeleteView.layout(mDeleteView.getLeft()+dx,mDeleteView.getTop()+dy,mDeleteView.getRight()+dx,mDeleteView.getBottom()+dy);
}else if (changedView==mDeleteView){
mContentView.layout(mContentView.getLeft()+dx,mContentView.getTop()+dy,mContentView.getRight()+dx,mContentView.getBottom()+dy);
}
Log.d(TAG,"dx --> "+dx);
//判断开关
if (mContentView.getLeft()==0 && currentStat!=SwipeState.CLOSE){
//应该是关闭
currentStat=SwipeState.CLOSE;
//这里则是关闭
mManager.clearCurrentLayout();
}else if (mContentView.getLeft()==-mDeleteWidth && currentStat!=SwipeState.OPEN){
currentStat=SwipeState.OPEN;
//走到这layout应该是打开的状态
mManager.setCurrentLayout(SwipeLayout.this);
}
}
@Override
public void onViewReleased(@NonNull View releasedChild, float xvel, float yvel) {
super.onViewReleased(releasedChild, xvel, yvel);
if (mContentView.getLeft()<-mDeleteWidth/2){
//打开
// mHelper.smoothSlideViewTo(mContentView,-mDeleteWidth,0);
open();
}else{
//关闭
// mHelper.smoothSlideViewTo(mContentView,0,0);
close();
}
}
@Override
public int getViewHorizontalDragRange(@NonNull View child) {
return mDeleteWidth;
}
@Override
public int clampViewPositionHorizontal(@NonNull View child, int left, int dx) {
if (child==mContentView){
//右正 左负
if (left>0)left=0;
if (left<-mDeleteWidth)left=-mDeleteWidth;
}else if (child==mDeleteView){
if (left>mContentWidth)
left=mContentWidth;
if (left<(mContentWidth-mDeleteWidth))
left=mContentWidth-mDeleteWidth;
}
Log.d(TAG,"left --> "+left);
return left;
}
};
@Override
public void computeScroll() {
if (mHelper.continueSettling(true)){
postInvalidateOnAnimation();
}
}
//产生了滑动冲突 根据滑动距离来判断是往哪里滑动
@Override
public boolean onTouchEvent(MotionEvent event) {
//如果当前有layout已经是打开 就不允许点击其他View 还可以滑动 则下面的逻辑不能执行
if (!mManager.isShouldSwipe(this)){
//先关闭已经打开的layout
// mManager.closeCurrentLayout(); 有卡顿移动到onIne
requestDisallowInterceptTouchEvent(true);
return true;
}
switch (event.getAction()){
case MotionEvent.ACTION_DOWN:
mDownX = event.getX();
mDownY = event.getY();
break;
case MotionEvent.ACTION_MOVE:
float moveX = event.getX();
float moveY = event.getY();
float delatX=moveX-mDownX;//X移动的距离
float delatY=moveY-mDownY;//Y移动距离
if (Math.abs(delatX)>Math.abs(delatY)){
//那么移动应该是水平方向 SwipeLayout处理 recylist不拦截
requestDisallowInterceptTouchEvent(true);//父view不拦截 子view消费
}
//更新downXy
mDownX=moveX;
mDownY=moveY;
break;
case MotionEvent.ACTION_UP:
break;
}
mHelper.processTouchEvent(event);
return true;
}
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
boolean result = mHelper.shouldInterceptTouchEvent(ev);
//如果当前有打开的 则需要拦截 给子View处理
if (!mManager.isShouldSwipe(this)){
//先关闭已经打开的layout
mManager.closeCurrentLayout();
result=true;
}
return result;
}
public void open(){
mHelper.smoothSlideViewTo(mContentView,-mDeleteWidth,0);
postInvalidateOnAnimation();
}
public void close(){
mHelper.smoothSlideViewTo(mContentView,0,0);
postInvalidateOnAnimation();
}
public void setOnSwipeClickListener(onSwipeClickListener onSwipeClickListener) {
mOnSwipeClickListener = onSwipeClickListener;
}
@Override
public void onClick(View v) {
if (mOnSwipeClickListener != null) {
switch (v.getId()) {
case R.id.swipe_top:
// mOnSwipeClickListener.onTopClick();
Toast.makeText(getContext(), "置顶", Toast.LENGTH_SHORT).show();
Log.d(TAG, "top --> " + "置顶");
break;
case R.id.swipe_delete:
// mOnSwipeClickListener.onDeleteClick();
Toast.makeText(getContext(), "删除", Toast.LENGTH_SHORT).show();
// Log.d(TAG, "DELETE --> " + "删除");
break;
}
}
}
public interface onSwipeClickListener{
void onTopClick();
void onDeleteClick();
void onStatusChange();
}
}
//滑动管理
package com.example.bilibili_qq50;
public class SwipeManager {
private SwipeManager(){
}
private static SwipeManager sManager=null;
public static SwipeManager getManager() {
if (sManager==null){
synchronized (SwipeManager.class){
if (sManager==null){
sManager=new SwipeManager();
}
}
}
return sManager;
}
private SwipeLayout currentLayout;//用来记录当前打开的SwipeLayout
public void setCurrentLayout(SwipeLayout layout) {
this.currentLayout = layout;
}
//判断是否能进行滑动 如果没有打开的 --> 则可以滑动
//如果有打开并且是本身 --> 判断打开的layout和当前按下的时候是同一个
public boolean isShouldSwipe(SwipeLayout swipeLayout){
if (currentLayout==null) {
//当前没有打开的layout
return true;
}else{
//说明有打开的
return currentLayout==swipeLayout;
}
}
//关闭已经打开的layout
public void closeCurrentLayout(){
if (currentLayout != null) {
currentLayout.close();
}
}
//清空当前所记录的已经打开的layout
public void clearCurrentLayout(){
currentLayout=null;
}
}
点击删除

删除逻辑:

运行


就打印点击删除的Log说明执行到了嘛。你再看看你回调里执行到了没。
,notifyItemChanged方法后面那个参数是count,也不明白你为什么有两个notify
如果你删除了,先不考虑效率,直接notify一下全部。看看可不可以 ,如果可以,就是你方法用错了。