3

我正在开发自定义 ViewGroup。它是某种径向菜单(类似于 android 相机应用程序中的选项菜单)。

我设法正确地布置和画孩子。我必须做的另一件事是覆盖触摸事件调度:

@Override
public boolean dispatchTouchEvent(MotionEvent ev) {
    for (int i=0; i<getChildCount(); i++) {
        CircularView child=(CircularView) getChildAt(i);
        if (child.viewMetrics.containsPoint(ev.getX(), ev.getY())) {
            child.dispatchTouchEvent(ev);
            return true;
        }
    }
    return false;
}

child.viewMetrics.containsPoint()如果事件坐标属于它们中的任何一个(方法调用,仔细检查,正常工作),我会遍历子级并调度事件。

似乎工作,但它并不完美。我注意到了这个问题:当我点击、按住手指并稍微移动它时,点击会中断。这是演示

我查看了超类实现,并且有很多代码。我的第一个想法是复制它,但它取决于许多私人课程。

如何确保触摸事件调度正常工作?(不仅是点击,还有所有其他手势?)如果没有简单的方法来做到这一点,我将不胜感激有关移植默认实现的任何评论或建议或任何指向有关该主题的有用信息的链接。

4

1 回答 1

12

调度 touchEvents 时,您应该将位置偏移到视图左侧/顶部。

导致单击滚动视图的 800x400(而 scrollX = 200)意味着您正在触摸 1000x400 的视图,然后您知道已触摸哪个视图,它的边界就像 ltrb(950, 0, 1050, 600 ),为了正确调度它,你应该在你调度的事件中偏移 x,y 的值,这意味着你发送一个 MotionEvent(50,400) 到子视图。

视图将正确处理 touchEvent 并将其分派给子级或自行处理。

提示是,有时 View while dispatching 会将事件偏移某个值,并且循环后下一个 MotionEvent 将不再等于原始事件,因此您应该将副本发送给孩子。

在简历中,它是这样的:

MotionEvent cp = MotionEvent.obtain(event);
cp.offset(-child.getLeft(), -child.getTop());
boolean consumed = child.dispatchTouchEvent(cp);
cp.recycle();
return consumed;

我已经覆盖了几个类的 dispatchTouchEvent/onTouchEvent,这确实可以正常工作。

另外:我确实观看了 youtube 视频,可能您的某些视图正在拦截触摸事件并向您的视图发送 ACTION_CANCEL,这就是您丢失事件的原因。(这发生在我身上,这就是我覆盖所有 View 类的 dispatch/onTouch 的原因)

于 2013-07-24T22:10:03.840 回答