Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Detect Status Bar Visibility / TYPE_SYSTEM_OVERLAY not resizing automatically

I'm using the well known TYPE_SYSTEM_OVERLAY method to create a full screen overlay that's always on top of other views.

On a Moto Atrix2 API15 and for each AVD from API 10 through 17 the overlay view resizes automatically (expands vertically) when the status bar is hidden by another app. The overlay appears to "stay on top" of all other views, as I think it should. When the status bar is in view again, the overlay reduces it's size automatically again (less vertical pixels, basically subtracting the height of the status bar).

This is the desired behavior and am inclined to think this is not the exception or flawed behavior due to it working on many different emulators as well as at least one device manufacturer (motorola), perhaps more, but I don't have access to addtl devices.

The problem: On a Samsung GS2 (API15) & also tested on Kindle Fire (API10?), the overlay does not automatically resize (fill the space where the status bar once was) when the status bar is hidden by another app (status bar behind full screen app). On these devices, after the view is created the first time I don't get any more events from an onSizeChanged override for the view.

Here's the pertinent code:

params = new WindowManager.LayoutParams( 
    1, WindowManager.LayoutParams.MATCH_PARENT, 
    WindowManager.LayoutParams.TYPE_SYSTEM_OVERLAY, 
    WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
    |WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL, 
    PixelFormat.TRANSPARENT);
wm.addView(sizeLayout, params);

sizeLayout has the onSizeChanged override.

I've played around with just about every windowmanager layoutparam I can find, including SYSTEM_ALERT, FLAG_LAYOUT_IN_SCREEN, etc. I won't sleep until I can figure this out!

Edit 11/30/12: I found this from @deviant: https://stackoverflow.com/a/9195733/1851478 which is basically what I'm doing, however the problem remains with certain devices not resizing the system_overlay automatically. Perhaps I should raise a bug.

More INFO: IF I force a redraw (or even just load the overlay app) while there is a full screen app at the top of the view tree, my overlay still does not draw over the space the status bar normally takes up (even though the status bar is not in view at the time of draw), so it seems as if the overlay is not "overlayed" on top of the frontmost window which is full screen (and I've both created and tested many full screen apps using a variety of methods to make them go full screen). On these devices, the only way to get the overlay to draw over the status bar (even if the status bar is not in view) is to use the flag FLAG_LAYOUT_IN_SCREEN, but then the size of the layout never changes, is always full screen, and thus back to the original problem why this works on some devices but not others.

Edit 12/12/12: So I haven't had any further luck on this, and I did try using getLocalVisibleRect on views, but unfortunately since my app doesn't own the SystemUI views it can't detect what's below the overlays. I suppose with a custom ROM I could do this, but I need a solution without root.

I do see other apps on the marketplace are having the same problem detecting the status bar on the non-working phones I listed above. Example: cool tool, omega statusbar & status bar +. Bounty raised.

Edit 12/19/12 Pictures added. Note that on a working device the gray area also "covers" the black area (any app that is currently full screen), the black area actually covers entire screen, I'm just showing the gray area as my overlay even though it is also full screen (minus or plus the height of the status bar depending on working/non-working device and whether it is in view or not).

enter image description hereenter image description here

like image 681
logray Avatar asked Nov 29 '12 17:11

logray


2 Answers

Hopefully i understand what you are after here but, in my app (TEAM BatteryBar) i had a similar problem. ( no root minimal permissions )

I couldn't detect a full screen on anything below API11 (and intermittent on some (Samsung mostly) devices above API11). So i made a custom listener for it by adding a second layout to the WindowManager with a different layout param then overrode the onLayout to check if the statusBar is still there or not by checking the window size. from there you can do what ever you need to to your main view.

I was going to tidy it up but it worked so i didn't :P code is over a year old and is from when i first started coding for android so yeah. Food for thought tho. hope it helps.

here is the code in a repo at my github with a copy paste straight out of my app on how i am using it. small snippet here

wm.addView(sizeLayout, params);// add your view

// then add the next one
Screendetect mDetector;
mDetector = new Screendetect(this);
mDetector.setOnFullScreenListener(new OnFullScreenListener() {
            @Override
            public void fsChanged(boolean FS_Bool) {
                // TODO rethink this to be better.... bit hacky...
                if (FS_Bool) {
                    Log.d("battbardetect", "Statusbar hidden");
                    FS_vissible(); // do what ever you need to
                } else if (!FS_Bool) {
                    Log.d("battbardetect", "Statusbar Vissible"); 
                    FS_hidden(); // do what ever you need to
                }
            }
        });
wm.addView(mDetector, params);
like image 75
pvyParts Avatar answered Oct 26 '22 00:10

pvyParts


I think this may be the same issue with hiding the titlebar on dialog windows where the system sets the visibility to hidden instead of gone. This causes the dialog window to get incorrectly centered.

For that, here's how I fix it. This might work for your situation but you may need to adjust it for the name of the status bar identifier.

Window window = dialog.getWindow();
View view = window.getDecorView();
int topPanelId = getResources().getIdentifier("topPanel", "id", "android");
LinearLayout topPanel = (LinearLayout) view.findViewById(topPanelId);
topPanel.setVisibility(View.GONE);
like image 1
Chuck D Avatar answered Oct 26 '22 00:10

Chuck D