ScaleGestureDetector不工作的ICS上及以下片段或一个ViewGroup布局中查看 [英] ScaleGestureDetector not working for View within Fragment or ViewGroup layout on ICS and below
问题描述
我的应用程序使用了支持包来实现对2.2以上片段
秒。
My application makes use of the support package to implement Fragment
s on 2.2 upwards.
我有一个查看
子类(姑且称之为 ZoomableView
),使得使用的ScaleGestureDetector
来检测捏缩放事件。这是在熟悉的方式进行;也就是说,在 onTouchEvent()
的 MotionEvent
,则通过使用检测 mScaleDetector .onTouchEvent(事件)
。 A SimpleOnScaleGestureListener
用于接收规模的事件。
I have a View
subclass (let's call it ZoomableView
) that makes use of ScaleGestureDetector
to detect pinch scaling events. This is done in the familiar way; that is, within onTouchEvent()
, the MotionEvent
s are passed to the detector using mScaleDetector.onTouchEvent(event)
. A SimpleOnScaleGestureListener
is used to receive the scale events.
本 ZoomableView
类始终显示为唯一的查看
A 片段中
(姑且称之为 ZoomableFragment
)。有应用程序内的两个用例吧。在一个用例,布局只包含的 ZoomableFragment
,包含 ZoomableView
。在第二个用例中, ZoomableFragment
将旁边另一个片段显示。这等片段
碰巧住房一个图形页面
,但使用图形页面的
是不相关的问题(问题仍然存在如果第二个片段
只包含一个普通的查看
)。
This ZoomableView
class is always displayed as the sole View
within a Fragment
(let's call it ZoomableFragment
). There are two use cases for it within the application. In one use case, the layout only consists of the ZoomableFragment
, containing the ZoomableView
. In the second use case, the ZoomableFragment
will be displayed alongside another Fragment. This other Fragment
happens to be housing a MapView
, but the use of MapView
isn't relevant to the problem (the problem still occurs if that second Fragment
just contains an ordinary View
).
实际的问题是,pre-杰利贝恩设备(特别是手机升级Froyo)上测试时,使用活动
时,显示twin- 片段
布局,的 ZoomableFragment
ZoomableView
ScaleGestureDetector
不起作用。当我说'不行',我可以在它处理 MotionEvent
S中的调试器看到,但没有在 SimpleOnScaleGestureListener方法
被调用。然而,使用活动
包含时的只有的的 ZoomableFragment
,规模检测不工作。如果我尝试对我的豆形软糖设备的应用,双 - 片段
情况的工作绝对没问题;即,尺度手势接收。
The actual problem is that when testing on a pre-Jellybean device (specifically, a Froyo phone), when using the Activity
that shows the twin-Fragment
layout, the ZoomableFragment
's ZoomableView
ScaleGestureDetector
doesn't work. When I say 'doesn't work', I can see in the debugger that it processes the MotionEvent
s, but none of the methods in the SimpleOnScaleGestureListener
are called. However, when using the Activity
that contains only the ZoomableFragment
, the scale detection does work. If I try the application on my JellyBean devices, the twin-Fragment
situation works absolutely fine; that is, the scale gestures are received.
我已搜索周围,我能找到的唯一的问题是,人们已经实施 OnScaleGestureListener
和$ P $由从<$ C $返回false工作pvented它C> onScaleBegin()。这不是我的问题在这里。
I've searched around and the only issue I can find is where people have implemented OnScaleGestureListener
and prevented it from working by returning false from onScaleBegin()
. That's not my issue here.
因此,在总结,一个 ScaleGestureDetector
不调用其侦听器时中使用时,应该做一个查看
在多个支撑上升级Froyo(Android 2.2的)片段
布局,我认为直至并包括ICS。但是,如果片段
是在屏幕上只有一个,探测器工作正常。此外,该问题不会对任何4.1+我的设备的Jellybean存在。
So in summary, a ScaleGestureDetector
doesn't call its listener when it should do when used within a View
on a multiple support Fragment
layout on Froyo (Android 2.2) and I assume up to and including ICS. If however the Fragment
is the only one on the screen, the detector works fine. Furthermore, the problem doesn't exist whatsoever on my 4.1+ Jellybean devices.
修改1 在我的双胞胎片段布局, ZoomableFragment
一直放在视方向右侧或底部。我只是做了一个有趣的现象是,如果我翻转的布局使得 ZoomableFragment
是在纵向上(而不是较低的片段),或者是在水平方向的左侧,则规模探测器的工作原理!因此,我怀疑这是值得做的 MotionEvent
getRawX()
/ <$结果之间的关系C $ C>的getX()(和Y的类似)的方法,使用碎片时。但是,当我翻转布局尚且如此,捏缩放则相邻图形页面
片段
不起作用!因此,在总结,在升级Froyo似乎 ScaleGestureDetector
只为工作在查看
包含在片段
有在屏幕的0,0一角。
EDIT 1 In my twin-Fragment layout, the ZoomableFragment
has always been placed on the right or bottom depending on orientation. An interesting observation I just made is that if I flip the layout such that the ZoomableFragment
is at the top (rather than being the lower fragment) in the portrait orientation, or is on the left in horizontal orientation, then the scale detector works! I therefore suspect that this is something to do with the relation between the results of the MotionEvent
getRawX()
/ getX()
(and similar for Y) methods, when Fragments are used. But when I flip the layout like this, pinch zooming then doesn't work for the adjacent MapView
Fragment
! So, in summary, on Froyo it seems that ScaleGestureDetector
is working only for a View
contained in a Fragment
that has a corner at 0,0 of the screen.
编辑2 现在我已经回答了这个问题我用一个简单的解决方案,我已经检查源 ScaleGestureDetector
上的grep后得出code。由于源甚至远ICS利用了 getRawX()
/ getRawY()
,我已经更新了此我首先想到的问题尽可能注明为ICS受到影响(我相信),而不仅仅是升级Froyo。
EDIT 2 I've now answered this question myself with a simple solution I've come to after inspecting the source for ScaleGestureDetector
on grepcode. Because the source even as far as ICS made use of getRawX()
/ getRawY()
, I've updated this question to state as far as ICS being affected (I believe), rather than just Froyo as I first thought.
编辑3 我做了一个简单的测试,以彻底消除任何与片段
s或任何东西在我的应用程序。我带着简单的谷歌图形页面
示例项目,简单地改变,因此大部分屏幕是采取了由一个布局的TextView
(重0.9)和一个小图形页面
坐镇具有重量的0.1底部。在我的Froyo的设备,它将不再捏变焦。在我的JB的设备,它的作用。因此,似乎我不会坚果,我已经对ICS遇到一个问题,用 GestureScaleDetector
及以下(我认为 - 当然升级Froyo,反正)对这个问题的答案给出了一个修补程序。
EDIT 3 I've done a simple test to completely eliminate anything to do with Fragment
s or anything else in my application. I took the simple Google MapView
example project and simply changed the layout so that most of the screen is taken up by a TextView
(weight 0.9) and a tiny MapView
sits at the bottom with a weight of just 0.1. On my Froyo device, it will no longer pinch zoom. On my JB device, it does. So it seems I'm not going nuts, and I have come across a problem with the GestureScaleDetector
on ICS and below (I think - certainly Froyo, anyway) for which the answer gives a fix.
推荐答案
从检查 ScaleGestureDetector
源$ C $ C上的grep code,我看到杰利贝恩版本 ScaleGestureDetector
不使用 getRawX()
和 getRawY()$的C $ C>的
MotionEvent
方法。但是,早期版本(升级Froyo,ICS等)的做的使用 getRawX()
和 getRawY()
为边坡计算的目的。这就是问题的所在,因为这意味着如果目标查看
不离开近0,0其顶部规模探测器将无法工作。
From inspecting the ScaleGestureDetector
source code on grepcode, I see that Jellybean versions of ScaleGestureDetector
do not make use of getRawX()
and getRawY()
methods of the MotionEvent
. However, the earlier versions (Froyo, ICS etc) do make use of getRawX()
and getRawY()
for the purpose of slop calculation. This is where the problem is, because it means that the scale detector won't work if the target View
doesn't have its top left near 0,0.
我得到了 ScaleGestureDetector
在我的自定义工作 ZOOMVIEW
,即使它被放置在右侧或底部通过简单地做这在 onTouchEvent()
:
I got the ScaleGestureDetector
to work on my custom ZoomView
, even with it being placed on the right or bottom, by simply doing this within onTouchEvent()
:
event.setLocation(event.getRawX(), event.getRawY());
mScaleDetector.onTouchEvent(event);
这导致的的 MotionEvent
内部调整偏移变量,使得的getX / Y
和 getRawX / Y
方法现在回到完全一样的价值。这prevents斜率计算失败。当然,规模探测器相对价值的作品,因此也无所谓关于X的绝对值/ Y.如果您有进一步的code依赖的绝对值,你可以做我做了后恢复他们什么
That causes adjustment of the MotionEvent
's internal offset variables such that the getX/Y
and getRawX/Y
methods now return exactly the same value. This prevents the slop calculation failing. The scale detector of course works with relative values and so it doesn't matter about the absolute values of X / Y. If you have further code that relies on the absolute values, you could do what I did to restore them after:
float originalY = event.getY();
float originalX = event.getX();
event.setLocation(event.getRawX(), event.getRawY());
mScaleDetector.onTouchEvent(event);
event.setLocation(originalX, originalY);
此外,如果我希望把我的片段
包含图形页面
在底部或右边,我已经使用图形页面的自定义子类
无论如何,所以我刚才添加的:
Furthermore, if I want to place my Fragment
that contains a MapView
on the bottom or right, I am already using a custom subclass of MapView
anyway and so I just added this:
public boolean onTouchEvent(MotionEvent event) {
// Work around required for ScaleGestureDetector.
// Before calling the scale detector, perform a work-around that is needed for earlier APIs (I suspect
// ICS and below, judging from inspection of ScaleGestureDetector) to make the MotionEvent give the
// same values for getY / getRawY and getX / getRawX. Wildly different values, caused by the View
// being nowhere near the screen origin (i.e. the View is on the right or the bottom) means the
// detector doesn't work.
event.setLocation(event.getRawX() - getLeft(), event.getRawY() - getTop());
return super.onTouchEvent(event);
}
现在,我的图形页面
将正确的片段
被放置在捏规模也不管。 (顺便说一句 - 完全OT对于这个问题,但如果你想知道,我放在图形页面
到片段
成功地使用 LocalActivityManager
解决方案在计算器上给出)。 修改:其实,事情并非100%正确的:地图不会围绕捏手势的中心放大。我认为这是与动作条/通知栏高度不被补偿做共达()
。
Now, my MapView
will pinch scale properly too, no matter where its Fragment
is placed. (By the way - totally OT to this question, but in case anyone is wondering, I placed a MapView
into a Fragment
successfully using the LocalActivityManager
solution as given on StackOverflow). EDIT: Actually, something is not 100% right: The map doesn't zoom around the center of the pinch gesture. I think it's to do with the ActionBar / notification bar height not being compensated for in the getTop()
.
这篇关于ScaleGestureDetector不工作的ICS上及以下片段或一个ViewGroup布局中查看的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!