简体   繁体   中英

How to find the source view of a MotionEvent ACTION_CANCEL

How can I find the view causing a MotionEvent ACTION_CANCEL? I have a view "A" which is receiving ACTION_CANCEL and I don't want that to happen. Somewhere, a view "B" is "consuming" the MotionEvent. I'm hoping there is a way to find out who is "B" so I can address this misfunctionality.

I've tried looking through my code for various OnTouchEvent() and OnInterceptTouchEvent() handlers but haven't yet found a culprit.

I've also put a break point at the problematic ACTION_CANCEL but am not able to recognize anything in the MotionEvent that might represent "B".

If a parent is intercepting the motion event, the only way to prevent this is to prevent the parent from intercepting that event. This can be managed well in two ways.

Without seeing specific code and wanting a generalised solution I would suggest the following.

I would suggest managing your touch events for the parents and the child by managing the
requestDisallowInterceptTouchEvent(boolean) and

onInterceptTouchEvent(android.view.MotionEvent) event handlers of every view/viewgroup within the affected views A, B C.

By disallowing parent intercepts in the child, this assists you in catching parent intercepts you haven't accounted for, and also to customise and vary the child elements from within one parent.

This must be managed from your highest parent of your view/viewGroup and managed through all parent and child relationships.

Checking for listviews, any element that has a inbuilt touch events.

android.com/training/gestures/viewgroup

In terms of finding the offending view that is intercepting the event, that cannot be answered except by the logic of:

Go through each parent to child/parent to child view. Methodically check the ontouch handling within each view/view group as shown in my diagram.

查看图表

There is some more detail in these answers here:
https://stackoverflow.com/a/30966413/3956566
https://stackoverflow.com/a/6384443/3956566

I'm sure you understand this, but to me, it's the simplest solution.

Beyond this, we'd need to look at your code to troubleshoot it.

If I got your question correct, you are receiving ACTION_CANCEL probably in the parent and you need to find that view. Given event X and Y, you can find view that contains these coordinates at the first moment ACTION_CANCEL occurred. Try calling this method either with top parent (android.R.id.content) or the ViewGroup you are dealing with.

private View findViewAt(View contentView, int eventX, int eventY) {
            ArrayList<View> unvisited = new ArrayList<View>();
            unvisited.add(contentView);
            while (!unvisited.isEmpty()) {
                View child = unvisited.remove(0);
                if(isViewContains(child, eventX, eventY) {
                    Log.i(TAG, "view found! ");
                    unvisited.clear();
                    return child;
                }
                if (!(child instanceof ViewGroup)){
                    continue;
                }
                ViewGroup group = (ViewGroup) child;
                final int childCount = group.getChildCount();
                for (int i=0; i< childCount; i++){
                    unvisited.add(group.getChildAt(i));
                }
            }
      return null;
    }


private boolean isViewContains(View view, int eventX, int eventY) {
    int[] location = new int[2];
    view.getLocationOnScreen(location);
    int x = location[0];
    int y = location[1];
    int width = view.getWidth();
    int height = view.getHeight();
    return eventX < x || eventX > x + width || eventY < y || eventY > y + height;
}

根据我的经验,一个使A视图收到ACTION_CANCEL事件的案例是在用户触摸A之后他们将手指拖出A区域,如果你遇到这种情况,添加一个方法来检查dispatchTouchEvent()上的位置可以救命。

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM