自定義View——可刪除 item 的 ListView(事件分發)
事件分發概述
Android 中觸摸事件主要由 dispatchTouchEvent, onInterceptTouchEvent, onTouchEvent 來控制。
觸摸屏幕時,首先會觸發 ViewGroup 的 dispathTouchEvent 方法,自定義 View 時,如果它在 ACTION_DOWN 返回 false, 則表示不再繼續向下執行,事件到此結束,如果返回了 true, 則下次繼續執行 dispatchTouchEvent 方法,返回 super.dispatchTouchEvent(ev) 則會執行 onInterceptTouchEvent/onTouchEvent.
View 是沒有 onInterceptTouchEvent 方法的,因為事件傳遞到 View 之後是一定交給自己處理了。ViewGroup 的 onInterceptTouchEvent 方法 返回 true 表示 要攔截事件,給自己處理,返回 false 表示不攔截,傳遞給子 View 處理,執行子 View 的 dispatchTouchEvent 方法。
執行到 onTouchEvent 方法,返回 true 表示不再給它的 ViewGroup 處理,自己處理完就結束,返回 false 表示自己可以做一些操作,再執行它的 ViewGroup 的 onTouchEvent 方法。
可刪除 item 的 ListView 思路
理解上面的描述之後,就可以結合上面文章中的例子來自己動手實現一個
從右向左滑動時,需要我們來處理(彈出PopupWindow),其餘的交由 ListView 處理
PopupWindow 是彈出狀態時,再次觸摸,則需要消失 PopupWindow, 事件到此結束
這裡貼出 dispatchTouchEvent 和 onTouchEvent 的代碼:
@Override
public boolean dispatchTouchEvent(MotionEvent ev) {
Log.e("ItemDeletableListView", "dispatchTouchEvent action : " + ev.getAction() + ", handleTouchEvent:" + handleTouchEvent + ", isPopupShow:" + isPopupShow);
Log.e("ItemDeletableListView", "dispatchTouchEvent mPwDelete.isShowing:" + mPwDelete.isShowing());
if (!handleTouchEvent) {
// 如果不需要處理觸摸事件,那麼久不做處理
return super.dispatchTouchEvent(ev);
}
switch (ev.getAction()) {
case MotionEvent.ACTION_DOWN:
if (isPopupShow) {
// 已經展示了 popup 的話,再次觸發 down 事件,則消失,並不再分發事件
mPwDelete.dismiss();
isPopupShow = false;
return false;
}
downX = ev.getX();
downY = ev.getY();
downPosition = pointToPosition(((int) downX), ((int) downY));
break;
case MotionEvent.ACTION_MOVE:
if (isPopupShow) {
// 如果 move 過程中展示了 popupwindow, 那麼不再分發事件
return false;
}
x = ev.getX();
y = ev.getY();
if (downX-x > touchSlop && downX-x > Math.abs(downY-y)) {
isSliding = true;
} else {
isSliding = false;
}
break;
case MotionEvent.ACTION_UP:
isSliding = false;
break;
}
return super.dispatchTouchEvent(ev);
}
@Override
public boolean onTouchEvent(MotionEvent ev) {
Log.e("ItemDeletableListView", "onTouchEvent action : " + ev.getAction() + ", isSliding:" + isSliding + ", downPosition:" + downPosition);
switch (ev.getAction()) {
case MotionEvent.ACTION_MOVE:
if (isSliding) {
View child = getChildAt(downPosition);
if (child == null) {
return super.onTouchEvent(ev);
}
isPopupShow = true;
int x = getWidth()/2+mPwDelete.getWidth()/2;
int y = child.getTop()+child.getHeight()/2;
Log.e("TAG", "popup x:" + x + ", y:" + y);
mPwDelete.showAtLocation(child, Gravity.TOP | Gravity.LEFT, x, y);
mPwDelete.update();
mTvDelete.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
mDeleteItemListener.deleteItem(downPosition);
mPwDelete.dismiss();
isPopupShow = false;
}
});
}
break;
case MotionEvent.ACTION_UP:
break;
}
return super.onTouchEvent(ev);
}
![](https://pic.pimg.tw/zzuyanan/1488615166-1259157397.png)
![](https://pic.pimg.tw/zzuyanan/1482887990-2595557020.jpg)
※json schema
※分散式框架spring-session實現session一致性使用問題
TAG:程序員小新人學習 |