Android 重写Listview实现左滑删除功能( 非常好用 )

本文记录了如何在Android中实现ListView的左滑删除功能,详细介绍了重写ListView的onTouchEvent方法,结合data.slideView实现ItemView的滑动交互。提供了demon下载链接及关键代码部分,包括自定义ListView、Adapter、布局文件和SlideView类的实现。

做一个笔记:Listview左滑删除功能,demon地址:https://download.csdn.net/download/qq_33749262/12634812。

1 . 重写ListView -> ListViewCompat
重写了onTouchEvent,当ACTION_DOWN时通过pointToPosition(x, y)找到当前touch的是哪一个item,然后通过data.slideView找到对应的 slideView,并且回调slideView的onRequireTouchEvent(event)方法,就把事件传给了每一个ItemView。这样就完成了一个类似QQ左滑动删除功能的ListView。


import android.content.Context;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
import android.widget.ListView;

public class ListViewCompat extends ListView {

    private SlideView mFocusedItemView;
    public ListViewCompat(Context context) {
        super(context);
    }
    public ListViewCompat(Context context, AttributeSet attrs) {
        super(context, attrs);
    }
    public ListViewCompat(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
    }

    public void shrinkListItem(int position) {
        View item = getChildAt(position);

        if (item != null) {
            try {
                ((SlideView) item).shrink();
            } catch (ClassCastException e) {
                e.printStackTrace();
            }
        }
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        switch (event.getAction()) {
            case MotionEvent.ACTION_DOWN: {
                int x = (int) event.getX();
                int y = (int) event.getY();
                int position = pointToPosition(x, y);
                if (position != INVALID_POSITION) {
                    Info data = (Info) getItemAtPosition(position);
                    mFocusedItemView = data.slideView;
                }
            }
            default:
                break;
        }

        if (mFocusedItemView != null) {
            mFocusedItemView.onRequireTouchEvent(event);
        }
        return super.onTouchEvent(event);
    }
}

2 . activity_main.xml布局文件
自定义ListView,需要的地方布置好就OK

    <com.lks.leftslidedeldemon.ListViewCompat
        android:id="@+id/_clock_list_value"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:divider="@color/_black"
        android:dividerHeight="1px"
        android:drawSelectorOnTop="false"
        android:listSelector="@android:color/transparent"
        android:scrollbars="none"
        android:fadingEdge="none"
        android:overScrollMode="never"/>

3 . PrivateListingAdapter代码

import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.TextView;
import java.util.ArrayList;
import java.util.List;

public class ListAdapter extends BaseAdapter implements SlideView.OnSlideListener{

    private Context mContext;
    private List<Info> mList;
    private LayoutInflater mInflater;
    // 上次显示了删除按钮的itemView;
    private SlideView mLastSlideViewWithStatusOn;

    public ListAdapter(Context content, List<Info> list) {
        mContext=content;
        mList = list;
        mInflater = LayoutInflater.from(content);
    }

    @Override
    public int getCount() {
        if (mList == null) {
            mList = new ArrayList<Info>();
        }
        return mList.size();
    }

    @Override
    public Object getItem(int i) {
        return mList.get(i);
    }

    @Override
    public long getItemId(int i) {
        return i;
    }

    @Override
    public View getView(final int position, View convertView, ViewGroup parent) {
        ItemHolder itemHolder;
        //
        View itemView = mInflater.inflate(R.layout.item_list, null);
        SlideView slideView = new SlideView(mContext);
        slideView.setContentView(itemView);
        itemHolder = new ItemHolder(slideView);
        slideView.setOnSlideListener(this);
        slideView.setTag(itemHolder);
        //
        Info info = mList.get(position);
        info.slideView = slideView;
        info.slideView.shrink();
        //
        itemHolder._txt_remark.setText(info.getRemark());
        itemHolder.deleteHolder.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                mList.remove(position);
                notifyDataSetChanged();
            }
        });
        return slideView;
    }

    @Override
    public void onSlide(View view, int status) {
        if (mLastSlideViewWithStatusOn != null&& mLastSlideViewWithStatusOn != view) {
            mLastSlideViewWithStatusOn.shrink();
        }

        if (status == SLIDE_STATUS_ON) {
            mLastSlideViewWithStatusOn = (SlideView) view;
        }
    }

    private class ItemHolder {
        public TextView _txt_remark;
        public ViewGroup deleteHolder;
        ItemHolder(View view)
        {
            _txt_remark = (TextView) view.findViewById(R.id._txt_remark);
            deleteHolder = (ViewGroup) view.findViewById(R.id.delete_merge_holder);
        }
    }
}

4 . delet_merge.xml布局文件

<?xml version="1.0" encoding="utf-8"?>
<merge xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <LinearLayout
        android:id="@+id/delete_merge_content"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="horizontal">
    </LinearLayout>

    <RelativeLayout
        android:id="@+id/delete_merge_holder"
        android:layout_width="120dp"
        android:layout_height="match_parent"
        android:background="#ff0000"
        android:clickable="true">
        <TextView
            android:id="@+id/delete_merge_delete"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_centerInParent="true"
            android:gravity="center"
            android:text="删除"
            android:textColor="#ffffff"/>
    </RelativeLayout>
</merge>

5 . SlideView类

import android.content.Context;
import android.util.AttributeSet;
import android.util.TypedValue;
import android.view.MotionEvent;
import android.view.View;
import android.widget.LinearLayout;
import android.widget.RelativeLayout;
import android.widget.Scroller;
import android.widget.TextView;

public class SlideView extends LinearLayout{

    private Context mContext;
    private LinearLayout mViewContent;
    private RelativeLayout mHolder;
    private Scroller mScroller;
    private OnSlideListener mOnSlideListener;
    // 删除按钮宽度
    private int mHolderWidth = 120;
    private int mLastX = 0;
    private int mLastY = 0;
    private static final int TAN = 2;

    public interface OnSlideListener {
        public static final int SLIDE_STATUS_OFF = 0;
        public static final int SLIDE_STATUS_START_SCROLL = 1;
        public static final int SLIDE_STATUS_ON = 2;
        public void onSlide(View view, int status);
    }

    public SlideView(Context context) {
        super(context);
        initView();
    }

    public SlideView(Context context, AttributeSet attrs) {
        super(context, attrs);
        initView();
    }

    private void initView() {
        mContext = getContext();
        mScroller = new Scroller(mContext);
        // 设置linearlayout的orientation为横向
        setOrientation(LinearLayout.HORIZONTAL);
        View.inflate(mContext, R.layout.delet_merge, this);
        mViewContent = (LinearLayout) findViewById(R.id.delete_merge_content);
        mHolderWidth = Math.round(TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, mHolderWidth, getResources().getDisplayMetrics()));
    }

    public void setButtonText(CharSequence text) {
        ((TextView) findViewById(R.id.delete_merge_delete)).setText(text);
    }

    /**
     * 设置左边内容View     
     * @param view
     */
    public void setContentView(View view) {
        mViewContent.addView(view);
    }

    public void setOnSlideListener(OnSlideListener onSlideListener) {
        mOnSlideListener = onSlideListener;
    }

    public void onRequireTouchEvent(MotionEvent event) {
        int x = (int) event.getX();
        int y = (int) event.getY();
        // 得到的相对于View初始x轴位置的距离
        int scrollX = getScrollX();
        switch (event.getAction())
        {
            case MotionEvent.ACTION_DOWN:
            {
                if (!mScroller.isFinished()) {
                    mScroller.abortAnimation();
                }
                if (mOnSlideListener != null) {
                    mOnSlideListener.onSlide(this, OnSlideListener.SLIDE_STATUS_START_SCROLL);
                }
                break;
            }
            case MotionEvent.ACTION_MOVE:
            {
                int deltaX = x - mLastX;
                int deltaY = y - mLastY;
                if (Math.abs(deltaX) < Math.abs(deltaY) * TAN) {
                    break;
                }
                int newScrollX = scrollX - deltaX;
                if (deltaX != 0) {
                    if (newScrollX < 0) {
                        newScrollX = 0;
                    } else if (newScrollX > mHolderWidth) {
                        newScrollX = mHolderWidth;
                    }
                    this.scrollTo(newScrollX, 0);
                }
                break;
            }
            case MotionEvent.ACTION_UP:
            {
                int newScrollX = 0;
                if (scrollX - mHolderWidth * 0.75 > 0) {
                    newScrollX = mHolderWidth;
                }
                this.smoothScrollTo(newScrollX, 0);
                if (mOnSlideListener != null) {
                    mOnSlideListener.onSlide(this,
                            newScrollX == 0 ? OnSlideListener.SLIDE_STATUS_OFF
                                    : OnSlideListener.SLIDE_STATUS_ON);
                }
                break;
            }
            default:
                break;
        }
        mLastX = x;
        mLastY = y;
    }

    public void shrink() {
        if (getScrollX() != 0) {
            this.smoothScrollTo(0, 0);
        }
    }

    private void smoothScrollTo(int destX, int destY) {
        // 缓慢滚动到指定位置
        int scrollX = getScrollX();
        int delta = destX - scrollX;
        mScroller.startScroll(scrollX, 0, delta, 0, Math.abs(delta) * 3);
        invalidate();
    }

    @Override
    public void computeScroll() {
        if (mScroller.computeScrollOffset()) {
            scrollTo(mScroller.getCurrX(), mScroller.getCurrY());
            postInvalidate();
        }
    }
}

6 .主代码调用

_clock_list_value = (ListViewCompat) findViewById(R.id._clock_list_value);
list = new ArrayList<>();
for (int i = 1; i <= 16; i++) {
    Info temp = new Info();
    temp.setRemark(String.valueOf(i));
    list.add(temp);
}
//
adapter = new ListAdapter(this, list);
_clock_list_value.setAdapter(adapter);
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值