Android實(shí)現(xiàn)左滑刪除列表功能
本文實(shí)例為大家分享了Android自定義左滑刪除列表的具體代碼,供大家參考,具體內(nèi)容如下
1、布局文件view_left_slide_remove.xml
包含一個(gè)RelativeLayout和TextView,RelativeLayout是實(shí)際界面,TextView是刪除按鈕。
<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="40dp"> <RelativeLayout android:id="@+id/view_content" android:layout_width="match_parent" android:layout_height="match_parent" /> <TextView android:id="@+id/tv_remove" android:layout_width="@dimen/left_slide_remove_width" android:layout_height="match_parent" android:layout_alignParentRight="true" android:gravity="center" android:text="刪除" android:textSize="16sp" android:textColor="@color/white" android:background="#ffff4b30" android:visibility="gone"/> </RelativeLayout>
2、自定義Adapter
LeftSlideRemoveAdapter類實(shí)現(xiàn)了BaseAdapter。
在getView方法中引用了view_left_slide_remove布局,提供getSubView來(lái)導(dǎo)入真正的布局。
OnItemRemoveListener是刪除監(jiān)聽器。
public static abstract class LeftSlideRemoveAdapter extends BaseAdapter { protected Context mContext; private OnItemRemoveListener mListener; public LeftSlideRemoveAdapter(Context context) { this.mContext = context; } @Override public 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是實(shí)際的界面 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(){ @Override public 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方法里面滑動(dòng)界面。
VelocityTracker類記錄手勢(shì)。
Scroller類進(jìn)行滑動(dòng)操作。
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); } // 起始位置,當(dāng)前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); } // 恢復(fù)狀態(tài) clear(); // 獲取當(dāng)前界面 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)) { // 開始滑動(dòng) 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、測(cè)試?yán)?/strong>
ContractAdapter繼承LeftSlideRemoveAdapter類。
LeftSlideRemoveActivity中使用LeftSlideRemoveListView類。
public class LeftSlideRemoveActivity extends Activity { private List<Map<String, String>> mContentList = new ArrayList<Map<String, String>>(); @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_left_slide_remove); Map<String, String> item = new HashMap<String, String>(); item.put("name", "Peter"); item.put("address", "ShangHai"); mContentList.add(item); item = new HashMap<String, String>(); item.put("name", "Lily"); item.put("address", "BeiJing"); mContentList.add(item); item = new HashMap<String, String>(); item.put("name", "Jack"); item.put("address", "GuangZhou"); mContentList.add(item); item = new HashMap<String, String>(); 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<String, String> 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; } }
顯示如下
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
- Android高仿QQ6.0側(cè)滑刪除實(shí)例代碼
- 詳解Android中實(shí)現(xiàn)ListView左右滑動(dòng)刪除條目的方法
- android RecyclerView側(cè)滑菜單,滑動(dòng)刪除,長(zhǎng)按拖拽,下拉刷新上拉加載
- Android仿微信滑動(dòng)彈出編輯、刪除菜單效果、增加下拉刷新功能
- Android 實(shí)現(xiàn)左滑出現(xiàn)刪除選項(xiàng)
- Android仿QQ列表左滑刪除操作
- Android使用CardView作為RecyclerView的Item并實(shí)現(xiàn)拖拽和左滑刪除
- Android 滑動(dòng)監(jiān)聽RecyclerView線性流+左右劃刪除+上下移動(dòng)
- Android開發(fā)中模仿qq列表信息滑動(dòng)刪除功能
- Android?Recyclerview實(shí)現(xiàn)左滑刪除功能
相關(guān)文章
Android 異步獲取網(wǎng)絡(luò)圖片并處理導(dǎo)致內(nèi)存溢出問題解決方法
Android異步獲取網(wǎng)絡(luò)圖片并處理圖片Out Of Memory內(nèi)存溢出如何解決呢?本文介紹了操作步驟,感興趣的朋友可以了解下或許對(duì)你有所幫助2013-02-02Android實(shí)現(xiàn)歌曲播放時(shí)歌詞同步顯示具體思路
歌曲播放時(shí)歌詞同步顯示,我們需要讀取以上歌詞文件的每一行轉(zhuǎn)換成成一個(gè)個(gè)歌詞實(shí)體,可根據(jù)當(dāng)前播放器的播放進(jìn)度與每句歌詞的開始時(shí)間,得到當(dāng)前屏幕中央高亮顯示的那句歌詞2013-06-06Android內(nèi)部存儲(chǔ)與外部存儲(chǔ)的示例講解
內(nèi)部存儲(chǔ)和外部存儲(chǔ)的概念隨著Android版本的更新也在發(fā)生不斷的變化。最早的內(nèi)部存儲(chǔ)指的是系統(tǒng)自帶的ROM存儲(chǔ),外部存儲(chǔ)指的是外置的Sdcard或者通過OTG掛在的USB存儲(chǔ)2023-03-03OpenGL Shader實(shí)現(xiàn)簡(jiǎn)單轉(zhuǎn)場(chǎng)效果詳解
轉(zhuǎn)場(chǎng)效果常出現(xiàn)再視頻剪輯當(dāng)中,用于銜接兩段視頻片段切換的過渡效果。本文將介紹如何利用OpenGL Shader實(shí)現(xiàn)簡(jiǎn)單的轉(zhuǎn)場(chǎng)效果,需要的小伙伴可以參考一下2022-02-02Android省市區(qū)三級(jí)聯(lián)動(dòng)控件使用方法實(shí)例講解
最近有需求需要實(shí)現(xiàn)省市區(qū)三級(jí)聯(lián)動(dòng),但是發(fā)現(xiàn)之前的實(shí)現(xiàn)不夠靈活,自己做了一些優(yōu)化。下面通過實(shí)例代碼給大家介紹下Android省市區(qū)三級(jí)聯(lián)動(dòng)控件使用方法2017-01-01Android入門之利用OKHttp實(shí)現(xiàn)斷點(diǎn)續(xù)傳功能
這篇文章主要為大家詳細(xì)介紹了Android如何使用OKHttp多線程制作像迅雷一樣的斷點(diǎn)續(xù)傳功能,文中的示例代碼講解詳細(xì),感興趣的可以了解一下2023-01-01Android xml實(shí)現(xiàn)animation的4種動(dòng)畫效果實(shí)例代碼
在Android應(yīng)用程序,使用動(dòng)畫效果,能帶給用戶更好的感覺,做動(dòng)畫可以通過XML或Android代碼來(lái)實(shí)現(xiàn)。本文給大家介紹Android xml實(shí)現(xiàn)animation的4種動(dòng)畫效果實(shí)例代碼,一起看看吧2016-05-05Android 關(guān)機(jī)彈出選擇菜單的深入解析
本篇文章是對(duì)Android 關(guān)機(jī)彈出選擇菜單進(jìn)行了詳細(xì)的分析介紹,需要的朋友參考下2013-06-06