FullScreen and Navigation Bar Color in a NativeScript Android app

The Story…

I’ve seen a few comments on various channels about how to change the status bar, navigation bar, and full screen layouts on Android in a NativeScript app. In this post I want to cover a few scenarios and how to achieve the specific layout you want in your app. So lets get started.

I’m going to assume you are familiar with NativeScript, if you aren’t then check out the getting started guide for a quick intro. Let us start with a fresh app using the CLI, path into the new app, and add the android platform.

tns create screenApp
cd screenApp
tns platform add android

Now that we have our new app, open your IDE and let’s modify the main-page.js file.

Full Screen with Transparent Status Bar

You can copy the next snippet and run it to see the result. The important parts are requiring the application and platform modules to easily add some checks for android and sdk versions as needed. Then in the pageLoaded function we will make the code changes to achieve the end result. In short we are setting the status bar to transparent then adding some flags to the Android Window. The last important piece is adding some padding to the first view in your layout. I’m getting the status bar height and using that as the top padding here.

var app = require("application");
var platform = require("platform");
var color = require("color");

// Event handler for Page "loaded" event attached in main-page.xml
function pageLoaded(args) {
    // Get the event sender
    var page = args.object;
    page.bindingContext = data;

    var View = android.view.View;

    if (app.android && platform.device.sdkVersion >= '21') {
        var window = app.android.startActivity.getWindow();
        // set the status bar to Color.Transparent
        window.setStatusBarColor(0x000000);

        var decorView = window.getDecorView();
        decorView.setSystemUiVisibility(
            View.SYSTEM_UI_FLAG_LAYOUT_STABLE
            | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
            | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
            // | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION // hide nav bar
            // | View.SYSTEM_UI_FLAG_FULLSCREEN // hide status bar
            | View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY);
    }

    var statusHeight = getStatusBarHeight();
    // // Need to add some padding to whatever your first View(widget)
    // var actionbar = page.actionBar._toolbar;
    // // Set the padding to match the Status Bar height
    // actionbar.setPadding(0, statusHeight, 0, 0);

     var lab = page.getViewById('myLabel').android;
     lab.setPadding(0, statusHeight, 0, 0);

}
exports.pageLoaded = pageLoaded;

// A method to find height of the status bar
function getStatusBarHeight() {
    var result = 0;
    var resourceId = app.android.currentContext.getResources().getIdentifier('status_bar_height', 'dimen', 'android');
    if (resourceId) {
        result = app.android.currentContext.getResources().getDimensionPixelSize(resourceId);
    }
    return result;
}

Resulting Layout

Screenshot_2016-03-09-22-54-42

FullScreen “Immersive” Mode

To read about using the “Immersive” mode in Android read the docs here. The Fullscreen immersive mode will give you the full device screen for your layout and allow the user to swipe near the edges of the screen to bring the navigation bar and status bar back into view momentarily. There are some specifics to achieving this correctly, but the following code change will give you what you need. Just uncomment two lines from the .setSystemUiVisibility() method from above.

var decorView = window.getDecorView();
        decorView.setSystemUiVisibility(
            View.SYSTEM_UI_FLAG_LAYOUT_STABLE
            | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
            | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
            | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION // hide nav bar
            | View.SYSTEM_UI_FLAG_FULLSCREEN // hide status bar
            | View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY);

The two flags needed are SYSTEM_UI_FLAG_HIDE_NAVIGATION  and SYSTEM_UI_FLAG_FULLSCREEN.

Resulting Layout

immersive_mode

At this point you could try various options with the different flags in the code to hide the navigation bar or just the status bar. So let’s move on to one final piece with the navigation bar and it’s a nice effect. COLOR.

Color the Navigation Bar

At the beginning of our pageLoaded function we have a call to the Android method .setStatusBarColor() to change the statusbar color. Well Android also has a nice method for the navigation bar –.setNavigationBarColor(), add the following line after your var window. *REMINDER* Do not forget to comment out the two flags we uncommented a moment ago (SYSTEM_UI_FLAG_FULLSCREEN and SYSTEM_UI_FLAG_HIDE_NAVIGATION). If you leave them enabled, you won’t have a status bar or navigation bar.

 window.setNavigationBarColor(new color.Color('#3489db').android);

 

Resulting Layout

Snip20160310_13

Conclusion

In this tutorial we covered the basic code for manipulating the Android Window using various flags and methods to style the status bar and navigation bar. I plan on making a plugin for the navigation bar styling with an XML attribute to avoid users having to deal with the native code. If you haven’t check out Burke Holland’s plugin called nativescript-statusbar which allows you to set the color of the iOS and Android statusbar with a simple XML tag. The plugin is listed on NPM here: https://www.npmjs.com/package/nativescript-statusbar I hope you’ve enjoyed reading and if you have any questions feel free to leave in the comments. Follow me on Twitter @BradWayneMartin for more NativeScript tutorials and information.

14 thoughts on “FullScreen and Navigation Bar Color in a NativeScript Android app

  1. Thanks for putting this together Brad!

    I’ll drop in one other tip that helped me out. In my case I wanted this code to not be tied to any individual view, as my app can potentially start on two different pages (depending on whether the user has an existing login token), so I ended up putting this bit of code in my app.js before I call start().

    
    var application = require("application");
    application.android.onActivityStarted = function() {
        // The code described in this article
    };
    application.start(...);
    

    Like

    1. Without debugging I would guess there​ is an issue existing the native Android View class then. That’s odd. Have you searched the nativescript repo to see if it’s been reported?

      Like

    1. Hi, the immersive mode flag is a global change on Android for the current app when it’s added. So all you would do to only use one on page is to apply it and then remove it when you’re navigating away from that page. Nativescript has several page life cycle events that you can use. The navigatingFrom is probably a good start for your question. Hope that helps.

      Like

  2. Hi, i applied the immersive mode to one page. But when i tap on the screen, the status bar appears and then it doesn’t disappear. How can i fix it?

    Like

  3. On line 11 in your first block of code:

    var View = android.view.View;

    where are you importing that android reference from? I’ve tried importing it from platform and it doesnt have any fields called ‘view’.

    Like

    1. Pete, `android.view.View` is part of the android native API. So it’s not being imported, you just have direct access to it with NativeScript with its foundation on providing direct access to native APIs. I’m sure you figured this out by now, sorry for the late reply.

      Like

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s