注意:我已更改此问题的原始标题。最初的标题是“如何一次使用几个GestureDetector实例?”,但我发现问题不是与几个探测器有关,而是与视图层次结构有关。问题的其余部分按原样保留,我决定不删除任何内容,只需阅读即可。请告知我是否应该废弃过时的零件,我已经准备好了,但不确定是否应该这样做。
我在另一个(容器)中有一个视图(按钮),我希望它们做两件事: 1)如果用户滚动任何视图(点击并移动),则滚动整个容器。 2)如果用户单击该按钮,则会为该按钮调用单击处理程序。
我的容器不是一个简单的视图,它允许在两个方向上滚动(here are the details),所以我设置了一个GestureDetector来检测滚动事件并滚动容器,感谢323go的建议。从附加到主容器视图的OnTouchListener的onTouch方法调用此检测器。
我的问题是按钮。
如果我设置onClick处理程序,它似乎完全吸收所有运动事件,所以如果我开始滚动按钮,我就无法滚动视图。
好的,也许我可以在按钮上设置另一个GestureDetector,以便处理点击和滚动?
不幸的是,这不起作用。按钮的onScroll处理程序在distanceX和distanceY参数中接收疯狂值。看起来容器视图和按钮都有自己的滚动计数器,因此当我滚动视图时,按钮会累积一些偏移量。
所以我的问题是:使用GestureDetector类的预期方式是什么?我可以在视图层次结构中使用多个检测器,是否可以将处理从一个检测器委托给另一个检测器?例如,如果孩子返回假,父母检测器可以处理该事件。
已添加:事实上,我对这样简单的“父对子”解决方案感到满意:在层次结构的最顶层视图中附加了唯一的GestureDetector,它接收所有事件并决定如何处理它们,所以如果它检测到滚动 - 它只是滚动整个视图而不通知任何人,但如果它检测到点击 - 它会在点击位置下方找到子视图并将点击转发给它。但这是一种真正的Android 方式吗?甚至可能吗?
进一步调查:我试图关注the advice given in comments below并让我的子手势检测器从其onScroll方法返回false。这没有帮助:如果子处理程序返回false,则根本不调用父处理程序。
但是我注意到如果子处理程序没有尝试滚动父视图,它将收到正确的值。
以下是我的处理程序的代码:
private class ParentHandler extends GestureDetector.SimpleOnGestureListener {
@Override
public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {
Log.d("UI", "Parent Scroll X: " + String.valueOf(distanceX) + " Y: " + String.valueOf(distanceY));
scrollBy((int)distanceX, (int)distanceY);
return true;
}
@Override
public boolean onSingleTapUp(MotionEvent e) {return true;}
@Override
public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {return true;}
@Override
public boolean onDown(MotionEvent e) {return true;}
};
private class ChildHandler extends GestureDetector.SimpleOnGestureListener {
@Override
public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {
Log.d("UI", "Child Scroll X: " + String.valueOf(distanceX) + " Y: " + String.valueOf(distanceY));
// The line below drives the handler crazy!
// But if I remove it, the view will not be scrolled at all
// because the parent handler is not called
// even if this handler returned false.
scrollBy((int)distanceX, (int)distanceY);
return false;
}
@Override
public boolean onSingleTapUp(MotionEvent e) {return true;}
@Override
public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {return true;}
@Override
public boolean onDown(MotionEvent e) {return true;}
};
注意第二个处理程序中的注释。
如果删除了疯狂的电话,以下是我在日志中获得的内容:
Parent Scroll X: -1.0 Y: 2.0
Parent Scroll X: 0.0 Y: 2.0
Parent Scroll X: -1.0 Y: 1.0
Parent Scroll X: -1.0 Y: 2.0
Parent Scroll X: 0.0 Y: 2.0
...
Child Scroll X: -1.0 Y: 2.0
Child Scroll X: 0.0 Y: 2.0
Child Scroll X: -1.0 Y: 1.0
Child Scroll X: -1.0 Y: 2.0
Child Scroll X: 0.0 Y: 2.0
但是当我尝试在子处理程序中移动视图时,值会变成这样的:
Child Scroll X: 13.0 Y: 22.0
Child Scroll X: -11.0 Y: -15.9999695
Child Scroll X: 11.0 Y: 17.00003
Child Scroll X: -10.0 Y: -16.00003
Child Scroll X: 11.0 Y: 19.99997
请注意,值是交替的:13后跟-11,下一个是11,然后是-10,依此类推。所以平均漂移似乎没问题,但是如果我只是将这些值传递给scrollBy调用,那么视图将会一直抖动并跳转到那里我一直在滚动它。
显然,在为子视图触发的onScroll中调用scrollBy存在一些问题。如果从父处理程序执行相同的调用,则没有问题。
那里可能有什么问题?
已添加:我已删除附加到父级的GestureDetector,但行为相同。
所以问题实际上如下。我需要在GestureDetector检测到滚动时滚动整个视图。要滚动视图,我调用scrollBy。如果为父视图触发了原始onTouch事件,则此方法有效,但如果为子视图触发了onTouch,则不会这样做:在后一种情况下,尝试滚动父视图会影响GestureHandler接收的值。
这样可行:
parent.onTouch - > detector.onTouchEvent - > parent.scrollBy
而这不是:
child.onTouch - > detector.onTouchEvent - > parent.scrollBy
其中探测器是相同的。
答案 0 :(得分:2)