The source code used in this paper: https://github.com/HeXiaosa/ItemDeletableListView
This article is based on reading this article. https://blog.csdn.net/lmj623565791/article/details/22961279 And combined with Andorid to explore the development of art.
Overview of event distribution
Touch events in Android are mainly controlled by dispatch Touch Event, onIntercept Touch Event and onTouch Event.
When touching the screen, the dispathTouchEvent method of ViewGroup is triggered first. When customizing View, if it returns false in ACTION_DOWN, it indicates that it will no longer continue to execute downward. Event ends here. If true is returned, the next time dispatchTouchEvent method is executed and super.dispatchTouchEvent(ev) is executed, onTouchEvent/onTouchEvent is executed.
View has no onInterceptTouchEvent method, because events must be handled by themselves after they are passed to View. ViewGroup's onInterceptTouchEvent method returns true to indicate that it wants to intercept the event, process it for itself, return false to indicate that it does not intercept, pass it to the sub-View processing, and execute the dispatchTouchEvent method of the sub-View.
Execute to the onTouchEvent method, return true to denote that it will no longer be processed by its ViewGroup, and finish processing by itself. Return false to denote that it can do some operations, and then execute its onTouchEvent method of ViewGroup.
ListView Ideas for Deletable Items
After understanding the above description, you can combine the examples in the above article to implement one by yourself.
- When sliding from right to left, we need to process (pop up PopupWindow), and the rest is handled by ListView.
- When the Popup Window is in a pop-up state and touched again, the Popup Window needs to disappear and the event is over.
Here is the code for dispatch TouchEvent and 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) { // If you don't need to deal with touch events, don't deal with them for a long time. return super.dispatchTouchEvent(ev); } switch (ev.getAction()) { case MotionEvent.ACTION_DOWN: if (isPopupShow) { // If popup has been shown, the down event is triggered again, then it disappears, and the event is no longer distributed. 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) { // If popupwindow is displayed in the move process, events are no longer distributed 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); }