ScaleGestureDetector不工作的ICS上及以下片段或一个ViewGroup布局中查看 [英] ScaleGestureDetector not working for View within Fragment or ViewGroup layout on ICS and below

查看:197
本文介绍了ScaleGestureDetector不工作的ICS上及以下片段或一个ViewGroup布局中查看的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我的应用程序使用了支持包来实现对2.2以上片段秒。

My application makes use of the support package to implement Fragments 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 MotionEvents 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 MotionEvents, 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(And​​roid 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 Fragments 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() 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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆