自定义ViewGroup.dispatchTouchEvent()无法正常工作

时间:2013-07-24 22:00:38

标签: android android-custom-view

我正在开发自定义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()方法调用,双重检查,正常工作),我会遍历子节点并调度事件。

似乎工作,但它并不完美。我注意到问题:当我点击时,握住我的手指并稍微移动它,点击就会中断。 Here's the demo

我看了superclass implementation,而且有很多代码。我的第一个想法是复制它,但这取决于许多私人课程。

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

1 个答案:

答案 0 :(得分:9)

调度touchEvents时,应将位置偏移到左/上方视图。

导致单击800x400的scrollview(当scrollX = 200时)意味着您正在触摸1000x400的视图,然后您知道哪个视图已被触摸并且它的边界类似于ltrb( 950,0,1050,600),要正确调度它,你应该在调度时偏移x,y的值,这意味着你将一个MotionEvent(50,400)发送到子视图。

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

一个提示是,有时是一个视图,而调度将把事件设置为某个值,并且下一个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)