使用ActionBarSherlock;遇到2.2和ICS / JB之间的View.getLocationOnScreen()不一致

时间:2012-07-27 12:36:02

标签: android actionbarsherlock

我有RelativeLayout,其大小占据了包含Activity的所有屏幕区域。也就是说,它会填充除通知栏以外的所有屏幕区域。

我正在使用ActionBarSherlock。 ActionBar使用getWindow().requestFeature(Window.FEATURE_ACTION_BAR_OVERLAY)设置为叠加模式。因此,我的RelativeLayout的高度从通知栏的正下方直到屏幕的底部,并且它所拥有的任何子View都可能放在ActionBar后面。因此ActionBar肯定在叠加模式下运行。我确认在运行2.2,4.0.x(ICS)和4.1(JB)的设备上就是这种情况。

因为我的应用程序在这个RelativeLayout中实现了拖放机制,所以我需要知道布局在屏幕上的位置,以便我可以更正getRawY()返回的绝对屏幕Y触摸值。为实现这一目标,在布局阶段完成后,我一直在mRelativeLayout.getLocationOnScreen()内调用onWindowFocusChanged()

在我的4.0和4.1设备上,对getLocationOnScreen()的调用产生的Y值与最顶层通知栏的高度(以像素为单位)相匹配。为了确定通知栏和ActionBar组合的高度,我将getLocationOnScreen()返回的Y值添加到ActionBarSherlock的getHeight()方法的结果中。

问题是,在2.2设备上进行测试时,getLocationOnScreen()返回的Y值已经是通知栏高度加上ABS高度。即使ABS设置为叠加模式,也是如此。

关于来自getLocationOnScreen()的令人难以置信的结果,有几个关于SO的问题;一个here有一个答案让我想放弃getLocationOnScreen(),而是通过从总屏幕高度减去布局的高度来计算RelativeLayout的前Y偏移:

DisplayMetrics dm = new DisplayMetrics();
this.getWindowManager().getDefaultDisplay().getMetrics(dm);
int mRelativeLayoutYOffs = dm.heightPixels - mRelativeLayout.getMeasuredHeight(); 

我发现这个结果的奇怪之处在于它似乎给了我与getLocationOnScreen()相同的不一致性。 2.2上发生的情况是.getMeasuredHeight()上对RelativeLayout的调用实际上似乎是给出了一个高度值,该高度值从RelativeLayout的实际高度减去了ActionBar高度,即使将ABS设置为叠加,我已经在视觉上确认它绝对处于叠加模式。

我现在能想到的最好的策略是根据操作系统版本区别对待getLocationOnScreen()的结果。如果它是2.2,那么我知道它包括ABS高度。如果4.0以上,则不会。 2.2和4.0之间的任何东西,我还不确定。也许人们可以帮助填补这些细节。也许差异是在本机支持ActionBar的操作系统版本中引入的?如果它是可预测的并且很好地定义了行为是什么,那么希望这将是一个安全的策略。

如果不这样做,是否有其他方法可以确定RelativeLayout的左上角和左上角位置以纠正绝对屏幕触摸值?

1 个答案:

答案 0 :(得分:5)

问题是因为我不应该使用getWindow().requestFeature(Window.FEATURE_ACTION_BAR_OVERLAY)。 Intead,我的自定义样式(继承自父ActionBarSherlock主题)需要包含:

<item name="android:windowActionBarOverlay">true</item>
<item name="windowActionBarOverlay">true</item>

此外,我说在2.2上ABS正在以叠加模式工作时说错了 - 事实上,事实并非如此。现在我正在使用上面的样式项,它现在在2.2中以叠加模式工作。

.getLocationOnScreen()现在正确返回Y值,该值仅代表我的2.2,4.0和4.1设备上的通知栏高度。