Forum Xamarin.Android

Announcement:

The Xamarin Forums have officially moved to the new Microsoft Q&A experience. Microsoft Q&A is the home for technical questions and answers at across all products at Microsoft now including Xamarin!

To create new threads and ask questions head over to Microsoft Q&A for .NET and get involved today.

Xamarin.Android: Hide StatusBar and Notification in Fullscreen mode

I am trying to hide statusbar and notification in fullscreen mode. User should not be able to pull/swipe down status/notification bar in Xamarin android.

In native android it is working fine with below property.

View decorView = getWindow().getDecorView(); 
int uiOptions = View.SYSTEM_UI_FLAG_FULLSCREEN;
decorView.setSystemUiVisibility(uiOptions);

getWindow().setFlags(WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY, WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY);

Equivalent to TYPE_APPLICATION_OVERLAY in xamarin not able to get.

Any solution for Xamarin.Android?

I have tried below properties for xamarin:

View decorView = Window.DecorView;
var uiOptions = (int)decorView.SystemUiVisibility;
var newUiOptions = (int)uiOptions;      
newUiOptions |= (int)SystemUiFlags.HideNavigation;
newUiOptions |= (int)SystemUiFlags.LayoutHideNavigation;
newUiOptions |= (int)SystemUiFlags.LayoutFullscreen;
newUiOptions |= (int)SystemUiFlags.Fullscreen;
newUiOptions |= (int)SystemUiFlags.ImmersiveSticky; 
decorView.SystemUiVisibility = (StatusBarVisibility)newUiOptions;

Window.AddFlags(WindowManagerFlags.TranslucentNavigation);
Window.AddFlags(WindowManagerFlags.TranslucentStatus);
Window.ClearFlags(WindowManagerFlags.ForceNotFullscreen);

Help will be appreciated. Thank you

Answers

  • jezhjezh Member, Xamarin Team Xamurai

    @rahuroid
    Could you please using the following code and try again?

      Call method:          immersive(this.Window, 0, 0);
        public void immersive(Window window, int color, float alpha)
        {
            if (Build.VERSION.SdkInt >= BuildVersionCodes.Lollipop)
            { // 21
                window.ClearFlags(WindowManagerFlags.TranslucentStatus);
                window.AddFlags(WindowManagerFlags.DrawsSystemBarBackgrounds);
                window.SetStatusBarColor(new Android.Graphics.Color(mixtureColor(color, alpha)));
    
                SystemUiFlags systemUiVisibility = (SystemUiFlags)window.DecorView.SystemUiVisibility;
                systemUiVisibility |= SystemUiFlags.LayoutFullscreen;
                systemUiVisibility |= SystemUiFlags.LayoutStable;
                window.DecorView.SystemUiVisibility = (StatusBarVisibility)systemUiVisibility;
            }
            else if (Build.VERSION.SdkInt >= BuildVersionCodes.Kitkat)
            { // 19
                window.AddFlags(WindowManagerFlags.TranslucentStatus);
                setTranslucentView((ViewGroup)window.DecorView, color, alpha);
            }
            else if (Build.VERSION.SdkInt >= BuildVersionCodes.JellyBean)
            { // 16
                SystemUiFlags systemUiVisibility = (SystemUiFlags)window.DecorView.SystemUiVisibility;
                systemUiVisibility |= SystemUiFlags.LayoutFullscreen;
                systemUiVisibility |= SystemUiFlags.LayoutStable;
                window.DecorView.SystemUiVisibility = (StatusBarVisibility)systemUiVisibility;
            }
        }
    
        public static int mixtureColor(int color, float alpha)
        {
            int a = (color & 0x000000) == 0 ? 0xff : color >> 24;
            return (color & 0xffffff) | (((int)(a * alpha)) << 24);
        }
    
        /** create a fake transparent bar*/
        public static void setTranslucentView(ViewGroup container, int color, float alpha)
        {
            if (Build.VERSION.SdkInt >= BuildVersionCodes.Kitkat)
            { // 19
                int _mixtureColor = mixtureColor(color, alpha);
                View translucentView = container.FindViewById(Android.Resource.Id.Custom);
                if (translucentView == null && _mixtureColor != 0)
                {
                    translucentView = new View(container.Context);
                    translucentView.Id = Android.Resource.Id.Custom;
                    ViewGroup.LayoutParams lp = new ViewGroup.LayoutParams(
                            ViewGroup.LayoutParams.MatchParent, getStatusBarHeight(container.Context));
                    container.AddView(translucentView, lp);
                }
                if (translucentView != null)
                {
                    translucentView.SetBackgroundColor(new Android.Graphics.Color(_mixtureColor));
                }
            }
        }
    
        /** get the height of statusbar */
        public static int getStatusBarHeight(Context context)
        {
            int result = 24;
           int resId = context.Resources.GetIdentifier("status_bar_height", "dimen", "android");
            if (resId > 0)
            {
                result = context.Resources.GetDimensionPixelSize(resId);
            }
            else
            {
                result = (int)TypedValue.ApplyDimension(ComplexUnitType.Dip,
                        result, Android.Content.Res.Resources.System.DisplayMetrics);
            }
            return result;
        }
    
  • rahuroidrahuroid Member ✭✭

    @jezh Above code is not working in Android Oreo 8.1, Not able to hide statusbar. My application is not overlaying above system app. Meaning When I pull/swipe down, Statusbar shouldn't be visible. It should get hidden.

  • JGoldbergerJGoldberger USMember, Forum Administrator, Xamarin Team, University Xamurai
    edited September 2018

    @rahuroid

    It does look like that Android constant, WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY, has not been added to the WindowManagerFlags enum yet in Xamarin Android. I will get an issue filed for that.

    However since it is really just an int constant (representing bit flags) with value of 2038, you can just cast 2038 to WindowManagerFlags type and that should work same as on native Android, e.g.:

    Window.SetFlags((WindowManagerFlags)2038, (WindowManagerFlags)2038 ); 
    

    I did a quick test and this seems to work, but it does disable touch on the app, and that is why the status bar cannot be shown by swiping down from the top. Basically the 2038 flag value is a combination of all of these individual flags [1]. IOW the below is identical to the above:

    Window.SetFlags(
        WindowManagerFlags.DimBehind | WindowManagerFlags.BlurBehind | WindowManagerFlags.NotTouchable | WindowManagerFlags.NotTouchModal | WindowManagerFlags.TouchableWhenWaking | WindowManagerFlags.KeepScreenOn | WindowManagerFlags.LayoutInScreen | WindowManagerFlags.LayoutNoLimits | WindowManagerFlags.Fullscreen,
        WindowManagerFlags.DimBehind | WindowManagerFlags.BlurBehind | WindowManagerFlags.NotTouchable | WindowManagerFlags.NotTouchModal | WindowManagerFlags.TouchableWhenWaking | WindowManagerFlags.KeepScreenOn | WindowManagerFlags.LayoutInScreen | WindowManagerFlags.LayoutNoLimits | WindowManagerFlags.Fullscreen);
    

    With the above code, you can test the behavior of removing individual flags and see the results.

    [1] decimal 2038 = binary 11111110110. So that is the 2,4, 16, 32, 64, 128, 256, 512, and 1024 bit flags set. Those bits correspond to the flags in the second code snippet above, i.e.:

    WindowManagerFlags.DimBehind = 2
    WindowManagerFlags.BlurBehind = 4
    WindowManagerFlags.NotTouchable = 16
    WindowManagerFlags.NotTouchModal = 32
    WindowManagerFlags.TouchableWhenWaking = 64
    WindowManagerFlags.KeepScreenOn = 128
    WindowManagerFlags.LayoutInScreen = 256
    WindowManagerFlags.LayoutNoLimits = 512
    WindowManagerFlags.Fullscreen = 1024

    EDIT: "Doh" moment. So the enum, is WindowManagerTypes, e.g.:

    global::Android.Views.WindowManagerTypes.ApplicationOverlay
    
  • elashielashi Member ✭✭

    @jezh thank you very much . Very nice code that gave me insights of how to set SystemUiVisibility !!!
    I gave up on this task for few months before I am back to figure out how to set this field.

  • GrahamMcKechnieGrahamMcKechnie AUMember ✭✭✭

    Don't use hardcoded dimensions or reflection for the status bar height as the following will not work with devices containing notches or corner cutouts, which can have different status bar heights. For an explanation see my earlier post after searching for ViewCompat.SetOnApplyWindowInsetsListener(toolbar, this);

    Don't use:-
    int resId = context.Resources.GetIdentifier("status_bar_height", "dimen", "android");

Sign In or Register to comment.