Android 自定义左滑删除列表

1、布局文件view_left_slide_remove.xml

包含一个RelativeLayout和TextView,RelativeLayout是实际界面,TextView是删除按钮。
<?xml version="1.0" encoding="utf-8"?>        

2、自定义Adapter

LeftSlideRemoveAdapter类实现了BaseAdapter。
在getView方法中引用了view_left_slide_remove布局,提供getSubView来导入真正的布局。
OnItemRemoveListener是删除监听器。

public static abstract class LeftSlideRemoveAdapter extends BaseAdapter {protected Context mContext;private OnItemRemoveListener mListener;public LeftSlideRemoveAdapter(Context context) {this.mContext = context;}@Overridepublic final View getView(final int position, View convertView, ViewGroup parent) {ViewHolder holder;if (convertView == null) {LayoutInflater inflater = LayoutInflater.from(mContext);convertView = inflater.inflate(R.layout.view_left_slide_remove, parent, false);holder = new ViewHolder();holder.viewContent = (RelativeLayout) convertView.findViewById(R.id.view_content);holder.tvRmove = (TextView) convertView.findViewById(R.id.tv_remove);convertView.setTag(holder);// viewChild是实际的界面holder.viewChild = getSubView(position, null, parent);holder.viewContent.addView(holder.viewChild);} else {holder = (ViewHolder) convertView.getTag();getSubView(position, holder.viewChild, parent);}holder.tvRmove.setOnClickListener(new View.OnClickListener(){@Overridepublic void onClick(View v) {if (mListener != null) {mListener.onItemRemove(position);notifyDataSetChanged();}}});return convertView;}public abstract View getSubView(int position, View convertView, ViewGroup parent);}private static class ViewHolder {RelativeLayout viewContent;View viewChild;View tvRmove;}public static interface OnItemRemoveListener {public void onItemRemove(int position);}

3、自定义左滑删除列表

在dispatchTouchEvent方法里面捕捉MotionEvent事件。
在onTouchEvent方法里面滑动界面。
VelocityTracker类记录手势。
Scroller类进行滑动操作。

public class LeftSlideRemoveListView extends ListView {    private final static int SNAP_VELOCITY = 600;    private Scroller mScroller;    private VelocityTracker mVelocityTracker;    private int mTouchSlop;    private boolean mIsSlide = false;    private int mDelta = 0;    private int mDownX;    private int mDownY;    private int mMaxDistence;    private int mSlidePosition = INVALID_POSITION;    private OnItemRemoveListener adapterListener;    private OnItemRemoveListener mRemoveListener = new OnItemRemoveListener() {        @Override        public void onItemRemove(int position) {            if (adapterListener != null) {                adapterListener.onItemRemove(position);            }            clear();            mSlidePosition = INVALID_POSITION;        }    };    private LeftSlideRemoveAdapter mRemoveAdapter;    private View mCurrentContentView, mCurrentRemoveView;    public LeftSlideRemoveListView(Context context) {        this(context, null);    }    public LeftSlideRemoveListView(Context context, AttributeSet attrs) {        super(context, attrs);        mScroller = new Scroller(context);        mTouchSlop = ViewConfiguration.get(getContext()).getScaledTouchSlop();        mMaxDistence = context.getResources().getDimensionPixelSize(                R.dimen.left_slide_remove_width);    }    @Override    public boolean dispatchTouchEvent(MotionEvent ev) {        switch (ev.getAction()) {            case MotionEvent.ACTION_DOWN:                addVelocityTracker(ev);                if (!mScroller.isFinished()) {                    return super.dispatchTouchEvent(ev);                }                // 起始位置,当前position                mDownX = (int) ev.getX();                mDownY = (int) ev.getY();                int position = pointToPosition(mDownX, mDownY);                if (position == mSlidePosition) break;                mSlidePosition = position;                if (mSlidePosition == INVALID_POSITION ) {                    return super.dispatchTouchEvent(ev);                }                // 恢复状态                clear();                // 获取当前界面                View childView = getChildAt(mSlidePosition - getFirstVisiblePosition());                mCurrentContentView = childView.findViewById(R.id.view_content);                mCurrentRemoveView = childView.findViewById(R.id.tv_remove);                break;            case MotionEvent.ACTION_MOVE:                if (mCurrentContentView == null) break;                if (Math.abs(getScrollVelocity()) > SNAP_VELOCITY                        || (Math.abs(ev.getX() - mDownX) > mTouchSlop                        && Math.abs(ev.getY() - mDownY) < mTouchSlop)) {                    // 开始滑动                    mIsSlide = true;                }                break;            case MotionEvent.ACTION_UP:                if (mCurrentContentView == null && mIsSlide) break;                // 如果左滑小于4/5,按钮不显示                if (mDelta < mMaxDistence * 4 / 5) {                    mCurrentRemoveView.setVisibility(View.GONE);                    scrollRight();                } else if (mDelta < mMaxDistence) {                    scrollLeft();                }                recycleVelocityTracker();                mIsSlide = false;                break;        }        return super.dispatchTouchEvent(ev);    }    @Override    public boolean onTouchEvent(MotionEvent ev) {        if (mIsSlide && mSlidePosition != INVALID_POSITION) {            final int action = ev.getAction();            int x = (int) ev.getX();            switch (action) {                case MotionEvent.ACTION_MOVE:                    addVelocityTracker(ev);                    int deltaX = mDownX - x;                    mDownX = x;                    mDelta += deltaX;                    if (mDelta < 0) {                        mCurrentContentView.scrollTo(0, 0);                        mDelta = 0;                        mCurrentRemoveView.setVisibility(View.GONE);                    } else if (mDelta >= mMaxDistence) {                        mDelta = mMaxDistence;                        mCurrentContentView.scrollTo(mMaxDistence, 0);                        mCurrentRemoveView.setVisibility(View.VISIBLE);                        mCurrentRemoveView.setTranslationX(0);                    } else {                        mCurrentContentView.scrollBy(deltaX, 0);                        mCurrentRemoveView.setVisibility(View.VISIBLE);                        mCurrentRemoveView.setTranslationX(mMaxDistence - mDelta);                    }                    break;            }            return true;        }        return super.onTouchEvent(ev);    }    // 右滑    private void scrollRight() {        final int delta = mDelta;        mScroller.startScroll(delta, 0, -delta, 0, Math.abs(delta));        mDelta = 0;        postInvalidate();    }    // 左滑    private void scrollLeft() {        final int delta = mMaxDistence - mDelta;        mScroller.startScroll(mDelta, 0, delta, 0, Math.abs(delta));        mDelta = mMaxDistence;        postInvalidate();    }    @Override    public void computeScroll() {        if (mScroller.computeScrollOffset()) {            mCurrentContentView.scrollTo(mScroller.getCurrX(), mScroller.getCurrY());            mCurrentRemoveView.setTranslationX(mMaxDistence - mScroller.getCurrX());            postInvalidate();            if (mScroller.isFinished()) {                mCurrentContentView.scrollTo(mDelta, 0);                mCurrentRemoveView.setTranslationX(0);            }        }    }    private void addVelocityTracker(MotionEvent event) {        if (mVelocityTracker == null) {            mVelocityTracker = VelocityTracker.obtain();        }        mVelocityTracker.addMovement(event);    }    private int getScrollVelocity() {        mVelocityTracker.computeCurrentVelocity(1000);        int velocity = (int) mVelocityTracker.getXVelocity();        return velocity;    }    private void recycleVelocityTracker() {        if (mVelocityTracker != null) {            mVelocityTracker.recycle();            mVelocityTracker = null;        }    }    private void clear() {        if (mCurrentContentView != null) {            mDelta = 0;            mCurrentContentView.scrollTo(0, 0);            mCurrentContentView = null;            mCurrentRemoveView.setVisibility(View.GONE);            mCurrentRemoveView = null;        }    }    @Override    public void setAdapter(ListAdapter adapter) {        if (adapter instanceof LeftSlideRemoveAdapter) {            super.setAdapter(adapter);            mRemoveAdapter = (LeftSlideRemoveAdapter) adapter;            mRemoveAdapter.mListener = mRemoveListener;        } else {            throw new IllegalArgumentException("Must be LeftSlideRemoveAdapter");        }    }    public void setOnItemRemoveListener(OnItemRemoveListener listener) {        adapterListener = listener;    }}

4、测试例子

ContractAdapter继承LeftSlideRemoveAdapter类。
LeftSlideRemoveActivity中使用LeftSlideRemoveListView类。

public class LeftSlideRemoveActivity extends Activity {    private List> mContentList = new ArrayList>();    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_left_slide_remove);        Map item = new HashMap();        item.put("name", "Peter");        item.put("address", "ShangHai");        mContentList.add(item);        item = new HashMap();        item.put("name", "Lily");        item.put("address", "BeiJing");        mContentList.add(item);        item = new HashMap();        item.put("name", "Jack");        item.put("address", "GuangZhou");        mContentList.add(item);        item = new HashMap();        item.put("name", "Mike");        item.put("address", "ShengZhen");        mContentList.add(item);        LeftSlideRemoveListView lv = (LeftSlideRemoveListView) findViewById(R.id.id_listview);        lv.setAdapter(new ContractAdapter(this));        lv.setOnItemRemoveListener(new LeftSlideRemoveListView.OnItemRemoveListener() {            @Override            public void onItemRemove(int position) {                mContentList.remove(position);            }        });    }    private class ContractAdapter extends LeftSlideRemoveListView.LeftSlideRemoveAdapter {        public ContractAdapter(Context context) {            super(context);        }        @Override        public int getCount() {            return mContentList.size();        }        @Override        public Object getItem(int position) {            return position;        }        @Override        public long getItemId(int position) {            return position;        }        @Override        public View getSubView(int position, View convertView, ViewGroup parent) {            ViewHolder holder;            if (convertView == null) {                convertView = getLayoutInflater().inflate(                        R.layout.listview_item_customdapter, parent, false);                holder = new ViewHolder();                holder.tvName = (TextView) convertView.findViewById(R.id.tv_name);                holder.tvAddress = (TextView) convertView.findViewById(R.id.tv_address);                convertView.setTag(holder);            } else {                holder = (ViewHolder) convertView.getTag();            }            Map itemData = mContentList.get(position);            holder.tvName.setText(itemData.get("name"));            holder.tvAddress.setText(itemData.get("address"));            return convertView;        }    }    private class ViewHolder {        TextView tvName;        TextView tvAddress;    }}
显示如下


更多相关文章

  1. Android中打电话的数据流程分析
  2. Android(安卓)Studio 快捷键中英文对译
  3. Android(安卓)与 SQLite
  4. java.lang.IllegalArgumentException: column '_id' does not ex
  5. Android(安卓)popupwindow 示例程序一
  6. New Android(安卓)App Project: R cannot be resolved to a vari
  7. android布局全屏显示,状态栏和导航栏透明设置
  8. 【Android】从无到有:手把手一步步教你自定义RecyclerView手势监
  9. 使用setContentView的方式更换布局文件从而更换界面

随机推荐

  1. Android(安卓)Handler机制剖析
  2. 详解 Android(安卓)的 Activity 组件
  3. Android开发者指南Activity and Task Des
  4. Android(安卓)Studio报错adb不是内部命令
  5. Android在任何地方模拟点击屏幕
  6. Android禁止横屏竖屏切换
  7. 【转】IDEA / Android(安卓)studio 使用g
  8. 在手机端运行python工具(python手机版)
  9. Android(安卓)操作SQLite数据库(初步)-在程
  10. Android基础之启动过程分析