I have a RelativeLayout
whose size takes up all screen area that is available to the containing Activity
. That is, it fills all screen area except for the notification bar.
I am using ActionBarSherlock. The ActionBar is set to overlay mode using getWindow().requestFeature(Window.FEATURE_ACTION_BAR_OVERLAY)
. Therefore, the height of my RelativeLayout
spans from immediately below the notification bar right down to the bottom of the screen, and any child View
s it holds could potentially be placed behind the ActionBar. The ActionBar is therefore definitely operating in overlay mode. I confirm this is the case on devices running 2.2, 4.0.x(ICS) and 4.1(JB).
Because my application implements a drag-and-drop mechanism within this RelativeLayout
, I need to know the layout's position on the screen so that I can correct the absolute screen Y touch values returned by getRawY()
. To achieve this, after the layout phase has been done, I have been calling mRelativeLayout.getLocationOnScreen()
inside of onWindowFocusChanged()
.
On my 4.0 and 4.1 devices, the call to getLocationOnScreen()
produced a Y value that matched the height, in pixels, of the very top notification bar. In order to determine the height of the notification bar and ActionBar combined, I would add the Y value returned by getLocationOnScreen()
to the result of ActionBarSherlock's getHeight()
method.
The problem is that when testing on a 2.2 device, getLocationOnScreen()
is returning a Y value that is already the notification bar height plus the ABS height. This is the case even though the ABS is set to overlay mode.
There are a few questions on SO regarding implausable results from getLocationOnScreen()
; the one here has an answer which gives me the idea to just abandon getLocationOnScreen()
and instead calculate the RelativeLayout
's top Y offset by subtracting the layout's height from the total screen height:
DisplayMetrics dm = new DisplayMetrics();
this.getWindowManager().getDefaultDisplay().getMetrics(dm);
int mRelativeLayoutYOffs = dm.heightPixels - mRelativeLayout.getMeasuredHeight();
What I find bizarre about the result of this though is that it seems to give me the same inconsistency as I get from getLocationOnScreen()
. What happens on 2.2 is that the call to .getMeasuredHeight()
on the RelativeLayout
actually seems to be giving a height value that has the ActionBar height subtracted from the actual height of the RelativeLayout
, even though the ABS is set to overlay and that I have visually confirmed it is definitely in overlay mode.
The best strategy I can think of doing at the moment is to just treat the result of getLocationOnScreen()
differently depending on the operating system version. If it's 2.2, then I know it includes the ABS height. If 4.0 onwards, it doesn't. Anything between 2.2 and 4.0, I'm not yet sure. Perhaps people can help fill those details in. Perhaps the difference is introduced in OS versions that support the ActionBar natively? If it is predictable and well defined what the behaviour is, then hopefully this would be a safe strategy.
Failing that, are there any suggestions for other means of determining the RelativeLayout
's top and left screen positions in order to correct the absolute screen touch values?