Android侧滑删除另一种实现,SwipeListView补充

来源:互联网 发布:nfc写卡器软件 编辑:程序博客网 时间:2024/06/13 04:28

前不久在在做聊天删除功能的时候使用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) {        //删除聊天逻辑        }      });

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

阅读全文
0 0