Customize the iOS Navigation Bar / Status Bar with NativeScript

As I’ve been learning more and more about NativeScript, one of the first tasks that I really dove into was learning how to customize the Navigation Bar for an iOS app. NativeScript has a Navbar component on the roadmap, but for now, it requires some knowledge about the underlying iOS implementation of UINavigationControllers, UIViewControllers and the like.  But fear not! I have braved the treacherous waters of StackOverflow and the Objective-C docs and emerged, victorious and unscathed.

1

In this article, I’ll go over a few of the more common tweaks that you might need to make to the Navigation Bar or Status Bar. While NativeScript is a cross-platform framework, these tweaks apply specifically to iOS. However, most of the items that I will cover here can also be implemented for Android.

In the process of learning to customize the Navigation Bar, I took a lot of inspiration from this post by Simon NG on AppCoda. It’s a fantastic article that goes through much of what can be done to the iOS Navigation Bar and Status Bar from an Objective-C point of view. I really enjoyed the way the post was laid out, so I’m going to use roughly the same format here to talk about the iOS Navigation Bar / Status Bar in NativeScript:

  • Showing And Hiding the Navigation Bar
  • Setting the Navigation Bar Title
  • Hiding the Back Button
  • Changing the Navigation Bar Background Color
  • Changing the Title Text Color
  • Changing The Title Text Style
  • Setting the Status Bar Style
  • Customizing the Color of the Back Button
  • Hiding the Back Button
  • Adding New Button Bar Items

NativeScript Default Navigation

NativeScript treats the initial page that is loaded as the root view controller. Any view that is navigated to after that is pushed onto the navigation queue using a UINavigationController. This means that on the first view, you won’t see a Navigation Bar at all. On each subsequent view, you will see it including a “< Back” button.

Most of the tweaks that are done require a reference to the UINavigationController, or the current UIViewController. You can obtain a reference to this controller from the frames tns module.

<Page xmlns="http://www.nativescript.org/tns.xsd" loaded="loaded" >
  <!-- ... -->
</Page>
exports.loaded = function(args) {
  var page = args.object;
  if (page.ios) {
    var controller = frameModule.topmost().ios.controller;
  }
};

Showing And Hiding The Navigation

The frame module reference allows for easy showing/hiding of the Navigation Bar at any time and on any page.

// hide the navbar
frameModule.topmost().ios.navBarVisibility = "never";

// show the navbar
frameModule.topmost().ios.navBarVisibility = "always";

2

Setting The Navigation Bar Title

Changing the title is really easy. Simply use the page.ios application object which exposes a title property.

// set the title
page.ios.title = 'Instaclone';

10

Hiding The Back Button

Sometimes it may be desirable to hide the back button. In the example used here, the user logs in to Instagram using OAuth and is then redirected to the feed page. By default, that feed page displays a back button.

3

This is not ideal as the user could then back into the OAuth process and the app would break. Hiding the back button requires getting an instance of the UIViewController’s navigation item, and invoking the setHidesBackButtonAnimated method.

var controller = frameModule.topmost().ios.controller;

// get the view controller navigation item
var navigationItem = controller.visibleViewController.navigationItem;

// hide back button
navigationItem.setHidesBackButtonAnimated(true, false);

8

Changing The Navigation Bar Background Color

The default iOS colors are ok, but no app is complete without a nice, pretty custom Navigation Bar color. Use the setBarTint method to change the bar color. You can use system constants like blueColor(), or you can define a custom one using RGBA. I use the handy program Sip, which samples colors and automatically provides them in this RGBA format.

var controller = frameModule.topmost().ios.controller;
var navigationBar = controller.navigationBar;

// set bar color to system blue constant
navigationBar.barTintColor = UIColor.blueColor();

// set bar color to a nice dark blue with RGBA
navigationBar.barTintColor = UIColor.colorWithRedGreenBlueAlpha(0, 0.24, 0.45, 1);

4

Changing The Title Text Color

The Navigation Bar is now a very hip shade of blue, but the text on it is still black, which is not very nice or hip. It would be better if it were white. We can change that by altering the titleTextAttributes of the Navigation Bar.

// change title color
navigationBar.titleTextAttributes = new NSDictionary([UIColor.whiteColor()], [NSForegroundColorAttributeName]);

11

Changing The Title Text Style

Not that you should, but you can change the style of the text in the Navigation Bar as well.  You can, for instance, give it a nice drop shadow to bring back that late 90s feel.

var controller = frameModule.topmost().ios.controller;
var navigationBar = controller.navigationBar;

// change title color and drop the shadow like it's hot
var shadow = new NSShadow();
shadow.shadowColor = UIColor.blackColor();
shadow.shadowOffset = CGSizeMake(1,2);
navigationBar.titleTextAttributes = new NSDictionary([UIColor.whiteColor(), shadow], [NSForegroundColorAttributeName, NSShadowAttributeName]);

12

Setting The Status Bar Style

The Status Bar (time, battery indicator) has a default style of “dark.” This can be changed by using one of the valid mapped enumerations for the UIStatusBarStyle. If you ever wonder just how NativeScript maps iOS types and functions for classes, you can find all of that in the cross-platform-modules repo inside the ios.d.ts file. No need to do any guesswork.

/*  change status bar style
    UIStatusBarStyleDefault,
    UIStatusBarStyleLightContent,
    UIStatusBarStyleBlackTranslucent,
    UIStatusBarStyleBlackOpaque */
navigationBar.barStyle = 1;

5

Changing The Back Button Color

If we did have a back button on this page, it would be the wrong color:

6

Simply set the tint color on the navigationBar to fix this.

navigationBar.tintColor = UIColor.whiteColor();

7

Adding Buttons To The NavBar

Additional buttons can be added to the Navigation Bar using markup.

<Page>
  <Page.optionsMenu>
    <MenuItem text="share" tap="shareAction" />
  </Page.optionsMenu>
</Page>

Buttons can also be added programmatically by building up UIBarButtonItems and then adding them to the rightBarButtonItems array on the navigationItem.

/*  Create bar button item

    first argument is what icon to show:

    UIBarButtonSystemItemDone,
    UIBarButtonSystemItemCancel,
    UIBarButtonSystemItemEdit,
    UIBarButtonSystemItemSave,
    UIBarButtonSystemItemAdd,
    UIBarButtonSystemItemFlexibleSpace,
    UIBarButtonSystemItemFixedSpace,
    UIBarButtonSystemItemCompose,
    UIBarButtonSystemItemReply,
    UIBarButtonSystemItemAction,
    UIBarButtonSystemItemOrganize,
    UIBarButtonSystemItemBookmarks,
    UIBarButtonSystemItemSearch,
    UIBarButtonSystemItemRefresh,
    UIBarButtonSystemItemStop,
    UIBarButtonSystemItemCamera,
    UIBarButtonSystemItemTrash,
    UIBarButtonSystemItemPlay,
    UIBarButtonSystemItemPause,
    UIBarButtonSystemItemRewind,
    UIBarButtonSystemItemFastForward,
    UIBarButtonSystemItemUndo,
    UIBarButtonSystemItemRedo,
    UIBarButtonSystemItemPageCurl */

// creates item with UIBarButtonSystemItemAction icon
var shareItem = new UIBarButtonItem(UIBarButtonSystemItem.UIBarButtonSystemItemAction, null, null);

// add item to navigation bar
var actionButtonItems = [shareItem];
navigationItem.rightBarButtonItems = actionButtonItems;

12

Enjoy the Native

One of my favorite parts of working with NativeScript is this ability to just drop down and start working with the underlying native APIs directly, but without that goofy message passing syntax that Objective-C uses. Once you get the hang of how the APIs work and how NativeScript maps them, there is no limit to the amount of customization that you can do to your apps with NativeScript.

Comments

  • Pingback: Dew Drop – April 15, 2015 (#1993) | Morning Dew()

  • Evan Wieland

    This is really awesome Burke! TNS is really going places.

  • emiloberg

    Tip:

    The Status Bar (time, battery indicator) inherits its background color from the Navigation Bar (back, page title, etc). But if you hide the Navigation Bar the Status Bar inherits the color from the Window background color instead. So if you want to change the color of the Status Bar with the Navigation Bar hidden you have to set the Window background color.

    Here’s an example of hiding the Nav bar and setting the status bar background to a gray-ish color.

    var iosFrame = frameModule.topmost().ios;
    if (iosFrame) {
    iosFrame.navBarVisibility = ‘never’;
    iosFrame.controller.view.window.backgroundColor = UIColor.colorWithRedGreenBlueAlpha(0.945, 0.953, 0.953, 1);
    }

    • burkeholland

      Great tip!

    • Keith Mattix

      But how do you change the text color if the navbar is hidden?

  • Oscar van der Leij

    I tried using the part of Adding Buttons To The NavBar programatically but the icon is not showing.

    var controller = frameModule.topmost().ios.controller;
    controller.navigationBarHidden = false;
    var navigationItem = controller.visibleViewController.navigationItem;
    var shareItem = new UIBarButtonItem(UIBarButtonSystemItem.UIBarButtonSystemItemAction, null, null);
    shareItem.tintColor = UIColor.whiteColor();
    var actionButtonItems = [shareItem];
    navigationItem.rightBarButtonItems = actionButtonItems;

    Any idea what could be wrong?

    • burkeholland

      This has now been superseded by the superior ActionBar component. A much better solution.

  • Niek Kruse

    I’m getting an error when I run the code to change the text color on iPad:

    “No initializer found that matches constructor invocation”
    Probably has to do with the NSDictionary constructur? It’s pretty strange cause it does work on iPhone with the same iOS version (8.1)

  • ricardogobbo

    Today, Instagram presents different colors for statusbar and navigationbar. How can I perform this?

    • burkeholland

      I’m not sure how to do it beyond using the preset styles.

  • What about Android Status Bar in Lollipop?

  • Camille

    I changed the color of the back button using navigationBar.tintColor and put it onpageload. But I noticed that the transition of color was visible, at pageload it displays blue and when it successfully loaded, it changes to the color I set on navigationBar.tintColor. How can I automatically change the color of the navigationbar without seeing the transition of color? Thanks

  • Andrey Luiz

    For android I used this answer: http://stackoverflow.com/a/32201322/679062