我正在开发自定义 ViewGroup。它是某种径向菜单(类似于 android 相机应用程序中的选项菜单)。
我设法正确地布置和绘制 child 。我必须做的另一件事是覆盖触摸事件调度:
@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 ,而且有很多代码。我的第一个想法是复制它,但它依赖于许多私有(private)类(class)。
如何确保触摸事件分派(dispatch)工作正常?(不仅是点击,还有所有其他手势?) 如果没有简单的方法,我将不胜感激任何关于移植默认实现的评论或建议,或任何指向有关该主题的有用信息的链接。
最佳答案
在调度 touchEvents 时,您应该将位置偏移到 View 左侧/顶部。
因为点击 800x400 的 ScrollView (而 scrollX = 200)意味着你正在触摸一个 1000x400 的 View ,然后你知道哪个 View 被触摸了,它的边界就像 ltrb(950, 0, 1050, 600),为了正确调度它,您应该在调度事件中偏移 x,y 的值,这意味着您向 subview 发送 MotionEvent(50,400)。
View 将正确处理 touchEvent 并将其分派(dispatch)给子级或自行处理。
还有一个提示,有时 View 在调度时会将事件偏移一些值,循环后下一个 MotionEvent 将不再等于原始事件,因此您应该向 children 发送一个副本。
在resume中,是这样的:
MotionEvent cp = MotionEvent.obtain(event);
cp.offset(-child.getLeft(), -child.getTop());
boolean consumed = child.dispatchTouchEvent(cp);
cp.recycle();
return consumed;
我重写了几个类的 dispatchTouchEvent/onTouchEvent,这确实能正常工作。
此外:我确实看过 youtube 视频,可能您的某些 View 正在拦截触摸事件并向您的 View 发送 ACTION_CANCEL,这就是您丢失事件的原因。 (这发生在我身上,这就是我覆盖所有 View 类的 dispatch/onTouch 的原因)
关于android - 自定义 ViewGroup.dispatchTouchEvent() 无法正常工作,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17845545/