2

On Android 4 and up (excluding 4.4) when an app goes full screen (with SYSTEM_UI_FLAG_HIDE_NAVIGATION), then after the first touch the navigation bar appears (with software navigation keys). This means that all my layouts are moved up and have smaller sizes. This makes an ugly jump of all the layouts. Is there a way to make the navigation bar overlay my layout instead of pushing it up?

I want to make a video player with YouTube like behavior, where the navigation bar overlays the video after the touch so the video does not move up and shrinks a bit, which is annoying. System/status bar is not a problem, just the navigation bar. Thank you.

shelll
  • 3,234
  • 3
  • 33
  • 67

4 Answers4

2

This works, need to put onCreate():

WindowManager.LayoutParams attributes = getWindow().getAttributes();
attributes.flags |= WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN | WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS;
getWindow().setAttributes(attributes);

More info you can find on link: http://www.thekirankumar.com/blog/2013/02/10/show-and-hide-android-notification-bar-without-causing-a-layout-jerk/

zarej
  • 913
  • 1
  • 11
  • 23
  • This does not work for me on Android 4.1. The video does still shrink, when the navigation bar is shown. But the media player controls are below the navigation bar. And the FLAG_LAYOUT_NO_LIMITS causes video flickering... – shelll Nov 07 '13 at 21:32
  • the flickering was caused by one add, and not these flags. but the video still gets smaller when the nav bar shows – shelll Nov 08 '13 at 06:55
  • You are right, not working on Android 4.1 I tested on 4.3. Check my other answer works much better then this solution even for 4.3. – zarej Nov 09 '13 at 12:55
2

Forget on my previously answer not working on all versions. The right approach is to find out navigation bar height and add bottom margin -navigationBarHeight. This is full working example work on all 4.1+ versions:

public static int getNavigationBarHeight(Context context) {
    Resources resources = context.getResources();
    int resourceId = resources.getIdentifier("navigation_bar_height", "dimen", "android");
    if (resourceId > 0) {
        return resources.getDimensionPixelSize(resourceId);
    }
    return 0;
}

@SuppressLint("NewApi")
private int getRealScreenSize(boolean returnWidth) {

    final DisplayMetrics metrics = new DisplayMetrics();
    Display display = getActivity().getWindowManager().getDefaultDisplay();
    Method mGetRawH = null, mGetRawW = null;

    //Not real dimensions
    display.getMetrics(metrics);
    int width = metrics.heightPixels;
    int height = metrics.widthPixels;

    try {
        // For JellyBeans and onward
        if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.JELLY_BEAN_MR1) {
            display.getRealMetrics(metrics);

            //Real dimensions
            width = metrics.heightPixels;
            height = metrics.widthPixels;
        } else {
            mGetRawH = Display.class.getMethod("getRawHeight");
            mGetRawW = Display.class.getMethod("getRawWidth");

            try {
                width = (Integer) mGetRawW.invoke(display);
                height = (Integer) mGetRawH.invoke(display);
            } catch (IllegalArgumentException e) {
                e.printStackTrace();
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            } catch (InvocationTargetException e) {
                e.printStackTrace();
            }
        }
    } catch (NoSuchMethodException e3) {
        e3.printStackTrace();
    }

    if (returnWidth) {
        return width;
    } else {
        return height;
    }
}

Following example code need to put somewhere after surface was created:

RelativeLayout.LayoutParams lp = (LayoutParams) surfaceView.getLayoutParams();
int screenHeight = getRealScreenSize(false);
int screenWidth = getRealScreenSize(true);
int navigationBarHeight = getNavigationBarHeight(getActivity());
lp.height = (int) (screenWidth / (16d / 9d));
lp.width = screenWidth;
int k = (lp.height - screenHeight) / 2;
lp.setMargins(0, -k, 0, (-k) - navigationBarHeight);
surfaceView.setLayoutParams(lp);

Note that surface view must have parent RelativeLayout.

zarej
  • 913
  • 1
  • 11
  • 23
  • 1
    There is one small error, below the comment "Not real dimensions" you assign width and height to wrong variables (w to h and h to w). This almost works for me. I have just a small move up and immediately down after the system navbar shows/hides (~2-4 pixels). from a normal viewing distance, on a 7" tablet", its not visible. – shelll Nov 11 '13 at 10:39
  • 1
    Thanks I corrected width/high assignment error. I try this on Nexus 7 (first generation, android 4.3) and Galaxy Tab 2 (android 4.1.2) and works great. Surface should not be centered vertically. – zarej Nov 12 '13 at 10:09
  • This works only if the `VideoView` has no centering. I need at least horizontal centering and with it enabled, the video starts shrinking again. Right now my video is placed in the top left corner, which looks ugly (for 4:3 videos). My `VideoView` has both width and height set to `match_parent`. Any ideas? – shelll Nov 15 '13 at 06:34
  • If you set centering, system is looking available screen size which is from top of screen to top of navigation bar and because of that you have shrinking when navigation bar is appear or disappear. System is recalculating available screen size. The only solution is to programmatically center VideoView by adding also margins left/right to its layout params. – zarej Nov 16 '13 at 09:29
  • You can also check and example in Eclipse - Choose Android Application Project and in Wizard select Fullscreen Activity – zarej Nov 18 '13 at 17:17
  • there is just one small issue with this solution. if a video has 4:3 aspect ratio then when the system UI shows (and the video controls) a black rectangle appears on the right side of the screen and partially overlaps the video. – shelll Feb 03 '14 at 06:56
  • This does also not take into account if the navigation bar is not below - like on Nexus 5 landscape mode, the navigation bar is on the right, not below. – riggaroo Sep 02 '14 at 14:23
0

In below links there have written details about working with " System UI " & " Work with SYSTEM_UI_FLAG_LOW_PROFILE , SYSTEM_UI_FLAG_VISIBLE & SYSTEM_UI_FLAG_HIDE_NAVIGATION" :

http://developer.android.com/about/versions/android-4.0.html#SystemUI https://developer.android.com/reference/android/view/View.html#setSystemUiVisibility(int) https://developer.android.com/reference/android/view/View.html#SYSTEM_UI_FLAG_HIDE_NAVIGATION

I believe another nice question about " Hide System Bar " with some nice answers :

Hide System Bar in Tablets

Hope these will help you to get your work done.

Happy coding !!!

Community
  • 1
  • 1
Siddiq Abu Bakkar
  • 1,949
  • 1
  • 13
  • 24
  • 1
    Hiding the navigation bar works without any problem and the layouts look good with visibile/invisible navigation bar. Problem is that the layouts are pushed up when the navigation bar shows (in case of the video player, the video is also a bit shrinked) and that is ugly "pop". I would like to have the video to not change its size and the navigation bar to overlay over the video. Like in the tablet YouTbe app. – shelll Nov 05 '13 at 09:43
0
View decorView = getWindow().getDecorView();
int uiOptions = View.SYSTEM_UI_FLAG_FULLSCREEN
                | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION
                | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
                | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
                | View.SYSTEM_UI_FLAG_LAYOUT_STABLE;
decorView.setSystemUiVisibility(uiOptions);

Those flags make system and navigation bars overlay your content

atermenji
  • 1,338
  • 8
  • 19
  • this only works for wide screen videos. if a video has an aspect ratio of 4:3 then the video is aligned to the left. so setting the left margin, to center it, is still needed. – shelll Feb 03 '14 at 06:52