標籤:android android listview 滑動刪除
一轉眼就15年了,希望大家15年升職加薪走上人生巔峰
這篇部落格是結合上一篇ListView滑動刪除之Viewgroup打造滑動控制項(修正版)部落格所完成的,先上個吧.
其實實現起來並不複雜
1,解決滑動衝突
因為我們的自訂滑動控制項和ListView本身的滑動事件會產生各種衝突,所以我們可以自訂ListView並重寫onInterceptTouchEvent方法。
我們先來瞭解一下android事件的分發,當使用者觸控螢幕幕時會先去調用ViewGroup的dispatchTouchEvent方法。
而在dispathTouchEvent方法中又會調用onInterceptTouchEvent方法,這個方法主要的目的就是用來攔截使用者的操作,具體的分發機制詳情可以看郭神的部落格 Android事件分發機制完全解析,帶你從源碼的角度徹底理解(下)。
我們這裡就Crowdsourced Security Testing道如果這個方法返回false則是touch事件全部由子view完成就可以,看看代碼。
/** * 判斷是否攔截事件 */public boolean onInterceptTouchEvent(MotionEvent ev) {float lastX = ev.getX();float lastY = ev.getY();switch (ev.getAction()) {case MotionEvent.ACTION_DOWN:mFirstX = lastX;mFirstY = lastY;int motionPosition = pointToPosition((int) mFirstX, (int) mFirstY);if (motionPosition >= 0) {currentItemView = getChildAt(motionPosition- getFirstVisiblePosition());mySwipeItem = (MySwipeItem) currentItemView.findViewById(R.id.myitem);}break;case MotionEvent.ACTION_MOVE:float dx = lastX - mFirstX;float dy = lastY - mFirstY;Log.d("TAG", "DX:" + dx);if (Math.abs(dx) >= 5 && Math.abs(dy) >= 5) {return false;}if (Math.abs(dx) < 5 && Math.abs(dx) > 0) {mySwipeItem.toOff();}break;default:break;}return super.onInterceptTouchEvent(ev);}
在這裡我就是在move的時候做判斷,如果條件滿足我們就認為使用者是在進行橫向滑動操作,而在down的時候擷取到listview的子view,當move條件不滿足開始進行縱向滑動的時候使控制項關閉。
2,使用回調介面
我們的效果為如果滑開了這個控制項下次再點擊除button以外的地方就關閉滑動控制項,我們可以使用介面回調來實現這個效果
public interface OnScrollState {public void scrollView();public void scrollOn(View view);}public void setOnScrollState(OnScrollState onScrollState) {this.mOnScrollState = onScrollState;}自訂了一個介面然後在touch的時候進行判斷
@Overridepublic boolean onTouchEvent(MotionEvent event) {int scrollX = getScrollX();int x = (int) event.getX();switch (event.getAction()) {case MotionEvent.ACTION_DOWN: {if (!mScroller.isFinished()) {mScroller.abortAnimation();}if (mOnScrollState != null) {mOnScrollState.scrollView();}break;}case MotionEvent.ACTION_MOVE: {int deltaX = x - lastX;// 計算滑動終點是否合法,防止滑動越界int newScrollX = scrollX - deltaX;if (deltaX != 0) {if (newScrollX < 0) {newScrollX = 0;} else if (newScrollX > mMaxDistancex) {newScrollX = mMaxDistancex;}this.scrollTo(newScrollX, 0);}break;}case MotionEvent.ACTION_UP: {int newScrollX = 0;// 這裡做了下判斷,當鬆開手的時候,會自動向兩邊滑動,具體向哪邊滑,要看當前所處的位置if (scrollX > mMaxDistancex / 2) {newScrollX = mMaxDistancex;}// 慢慢滑向終點this.smoothScrollTo(newScrollX, 0);if (mOnScrollState != null && newScrollX == mMaxDistancex) {mOnScrollState.scrollOn(this);}break;}}lastX = x;return true;}在Main中進行調用控制項的關閉方法
@Overridepublic void scrollView() {if (mLastItem != null) {mLastItem.toOff();}}@Overridepublic void scrollOn(View view) {mLastItem = (MySwipeItem) view;}
3,缺點
很簡單就實現了滑動效果不是麼。。。。但是我們會發現我們自己的listview的onItemClick方法不起作用了!!,因為我們重寫了onInterceptTouchEvent方法,但是我們的滑動控制項中的textView以及button還是可以用onclick的,所以還有一種listview的滑動刪除方法高仿對話列表滑動刪除效果。
4,後記
不要問我為什麼自己不寫一個完美的,我才不會說是因為我寫不出來又犯懶了。。。。新手可以學習借鑒瞭解一下android的分發機制,但要是真的要用到項目中,我還是建議去Github上down一個成熟的
項目源碼
Android 結合滑動控制項ListView滑動刪除