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/tech/app/5658.html

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

相关推荐

发表回复

登录后才能评论