Facebook Twitter Gplus LinkedIn RSS
 
 
Home » Blog » Using the Native TabBar Plugin in Cordova

Using the Native TabBar Plugin in Cordova

Published on March 26th, 2012

Update: This post is a bit outdated. NativeControls has been updated. Click here to read more.

A couple of people that I know have been struggling with getting the Native TabBar in Cordova functioning since the name change from PhoneGap to Cordova. This plugin, called NativeControls, allows a Cordova developer to access the native Tabbar (as well as a few other windows and popups). Given all the issues that we’ve had over the years with fixed footers, this is an excellent way to use xCode’s native navigation tool and tie it back into your web-based App with calls to javascript.

If you aren’t already familiar with Cordova (or PhoneGap) plugins, then this short tutorial will seem impossible.

  1. Download the updated version of NativeControls from GistHub.
  2. Drag the .h and .m files into the Plugin folder of your xCode project and add “NativeControls” to the Cordova.plist plugins list as both the key and value.
  3. Add the javascript file to your index.html header.
  4. 1
    2
    
    script src="js/cordova-1.5.0.js"></script>
    <script src="js/NativeControls.js"></script>
    script src="js/cordova-1.5.0.js"></script>
    <script src="js/NativeControls.js"></script>
  5. Add the code for your own javascript.
  6. 1
    
    <xmp><script src="js/controls.js"></script></xmp>
    <xmp><script src="js/controls.js"></script></xmp>

    And then the body of this javascript file.

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    
    $(document).ready( function() {
        document.addEventListener("deviceready", onDeviceReady, false);
    });
     
    function onDeviceReady() {
     
      // Initializating TabBar
      nativeControls = window.plugins.nativeControls;
      nativeControls.createTabBar();
     
      // Books tab
      nativeControls.createTabBarItem(
        "books",
        "Books",
        "tabButton:Recents",
        {"onSelect": function() {
          alert('books');
        }}
      );
      
      // Stats tab
      nativeControls.createTabBarItem(
        "finished",
        "Finished",
        "tabButton:Recents",
        {"onSelect": function() {
          alert('stats');
        }}
      );
      
      // About tab
      nativeControls.createTabBarItem(
        "about",
        "About",
        "tabButton:Recents",
        {"onSelect": function() {
          alert('about');
        }}
      );
      // Compile the TabBar
      nativeControls.showTabBar();
      nativeControls.showTabBarItems("books", "finished", "about");
      nativeControls.selectTabBarItem("books");
    }
    $(document).ready( function() {
        document.addEventListener("deviceready", onDeviceReady, false);
    });
    
    function onDeviceReady() {
    
      // Initializating TabBar
      nativeControls = window.plugins.nativeControls;
      nativeControls.createTabBar();
    
      // Books tab
      nativeControls.createTabBarItem(
        "books",
        "Books",
        "tabButton:Recents",
        {"onSelect": function() {
          alert('books');
        }}
      );
      
      // Stats tab
      nativeControls.createTabBarItem(
        "finished",
        "Finished",
        "tabButton:Recents",
        {"onSelect": function() {
          alert('stats');
        }}
      );
      
      // About tab
      nativeControls.createTabBarItem(
        "about",
        "About",
        "tabButton:Recents",
        {"onSelect": function() {
          alert('about');
        }}
      );
      // Compile the TabBar
      nativeControls.showTabBar();
      nativeControls.showTabBarItems("books", "finished", "about");
      nativeControls.selectTabBarItem("books");
    }
  7. I had an issue with the NativeControl where nothing would happen, so I created the following function at the end of the javascript file. Be sure that if you do this that you delete the function that looks kinda like this one at the end of the file.
  8. 1
    2
    3
    4
    5
    6
    7
    8
    
    NativeControls.install = function() {
        if ( !window.plugins )
            window.plugins = {};
        if ( !window.plugins.NativeControls ) {
            window.plugins.nativeControls = new NativeControls();
        }
    }
    Cordova.addConstructor(NativeControls.install);
    NativeControls.install = function() {
        if ( !window.plugins )
            window.plugins = {};
        if ( !window.plugins.NativeControls ) {
            window.plugins.nativeControls = new NativeControls();
        }
    }
    Cordova.addConstructor(NativeControls.install);

While we are at it, let’s add support for orientation changes. Perhaps it will teach us a little about plugins. Don’t worry, I will make the code available to download.

Add the following function to your javascript.

1
2
3
4
function orientationChange() {
    var nativeControls = window.plugins.nativeControls;
    nativeControls.resizeTabBar();
}
function orientationChange() {
    var nativeControls = window.plugins.nativeControls;
    nativeControls.resizeTabBar();
}

And of course, make sure you call this with a listener (the second one).

1
2
3
4
$(document).ready( function() {
    document.addEventListener("deviceready", onDeviceReady, false);
    window.addEventListener("resize", orientationChange, false);
});
$(document).ready( function() {
    document.addEventListener("deviceready", onDeviceReady, false);
    window.addEventListener("resize", orientationChange, false);
});

Now for the meat of the code. Add the following to your .m file.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
/**
 * Resize the tab bar on Orientation Change
 * @brief resize the tab bar on rotation
 * @param arguments unused
 * @param options unused
 */
- (void)resizeTabBar:(NSArray*)arguments withDict:(NSDictionary*)options {
    CGFloat height   = 49.0f;
    CGRect webViewBounds = self.webView.bounds;
    webViewBounds.size.height += height;    
    CGRect tabBarBounds = CGRectMake(
         webViewBounds.origin.x,
         webViewBounds.origin.y + webViewBounds.size.height - height,
         webViewBounds.size.width,
         height
    );
    webViewBounds = CGRectMake(
         webViewBounds.origin.x,
         webViewBounds.origin.y,
         webViewBounds.size.width,
         webViewBounds.size.height - height
    );
    
    [tabBar setFrame:tabBarBounds];
    [self.webView setFrame:webViewBounds];
}
/**
 * Resize the tab bar on Orientation Change
 * @brief resize the tab bar on rotation
 * @param arguments unused
 * @param options unused
 */
- (void)resizeTabBar:(NSArray*)arguments withDict:(NSDictionary*)options {
    CGFloat height   = 49.0f;
    CGRect webViewBounds = self.webView.bounds;
    webViewBounds.size.height += height;    
    CGRect tabBarBounds = CGRectMake(
         webViewBounds.origin.x,
         webViewBounds.origin.y + webViewBounds.size.height - height,
         webViewBounds.size.width,
         height
    );
    webViewBounds = CGRectMake(
         webViewBounds.origin.x,
         webViewBounds.origin.y,
         webViewBounds.size.width,
         webViewBounds.size.height - height
    );
    
    [tabBar setFrame:tabBarBounds];
    [self.webView setFrame:webViewBounds];
}

And as every good developer knows, don’t forget to add the header declaration in the .h file.

1
- (void)resizeTabBar:(NSArray*)arguments withDict:(NSDictionary*)options;
- (void)resizeTabBar:(NSArray*)arguments withDict:(NSDictionary*)options;

Last but not least, add the following code to the NativeControls.js file.

1
2
3
NativeControls.prototype.resizeTabBar = function() {
    Cordova.exec("NativeControls.resizeTabBar");
};
NativeControls.prototype.resizeTabBar = function() {
    Cordova.exec("NativeControls.resizeTabBar");
};

Then when you hit compile in xCode, the magic happens. If you have any questions or require additional assistance, feel free to leave a comment below and I shall try my best. Also, be sure to look at all the comments included in the NativeControls.m file. They really detailed what all the parameters mean within each function.

Download: [download id=2 format=1]

About the Author: Sprawl

Stephen Russell is a Mobile App developer and all around IT geek that spends his days running data centers and his nights coding. This site is the go to place for all of zSprawl's work and the infamous development blog. In his free time, he enjoys tinkering with web code, playing video games, and otherwise plotting to take over the Internets.

 

28 Responses

  1. dartox

    maaaaan, i don’t get it. i did the exact same steps, and my app is always showing nothing!!

  2. Lukas

    Hey, thanks for this great tutorial! Works perfect under iOS 5.0 (in Simulator).
    With iOS 5.1 (iPhone & Simulator) it’s only working in portrait mode. In landscape mode is nothing to see…
    Have you an idea, how to work around this issue?
    Thanks,
    Lukas

  3. smeers

    I’m trying to implement the NativeControls, but it won’t port over to my iPhone. It shows up and works perfectly in the simulator, but the actual device will not show the tab bar. Any ideas?

  4. JonW

    I found your site via the jQuery Mobile forum and I have to say that this clever little piece of code is a life saver! No more slow tabs in my jQM app (despite upgrading to 1.1.0 and using “on tap”, it’s still not fast enough). You’ve made it so clean and easy to implement, so thank you!

    I have one issue. Can you help?

    When I specify the height of the tab bar – it works until I tap any of the tab bars, at which point the bar returns to the default size (49 according to your docs). Why is this? I’m using the following:

    nativeControls.showTabBar({ ‘position’: ‘bottom’, ‘height’: ’56’ });

    I’ve also tried changing it in the NativeControls.m file (height = 56.0f) and the same thing happens.

    And finally, whenever I change tabs while running in debug mode, I see a “TabBar Resizing” comment in my console output. Is this correct?

    Thanks again for making this code freely available, you have saved me from going insane with the slow tapping issue in mobile Safari!

    • Hmmm… you know, I’ve never tried to override the height. I can’t say that I know offhand, but I will look this weekend as I’ve been trying to fix the NavBar (the title bar) to work properly with two buttons. I do know that Apple likes to insist you stick with their default sizes for UI unless you have a good reason, whatever that means.

      • JonW

        Ah, that makes sense then. Not to worry – it was only because I show a jQM navbar if the device is not iPhone and my navbar was 56px. I will size it down to 49px in CSS instead.

  5. rxraza

    Thanks for the tutorial, I followed instructions but I can’t get to display the tab bar in my app. I am using iPhone Simulator 5.0 on OSX 10.7.3. Please help

    Below is what I found out..

    nativeControls.createTabBar() call not returning

    inside the function I put alerts, I can see alerting saying ‘creating’ but I do not see an alert that says ‘created’. That tells me that NativeControls.createTabBar did not return.

    NativeControls.prototype.createTabBar = function() {
    alert(‘creating’);
    cordova.exec(“NativeControls.createTabBar”);
    alert(‘created’);
    };

    Is there anything I am missing

    • A couple of things to check.

      1) Did you remember to include “NativeControls” in the pList file and drag the .m and .h files to the Plugins folder in xCode?

      2) Did you fix the install function in the js file? Does it fire? Put alerts.

      3) Lastly, download the jQuery Mobile App from the download section and open it in xCode to compare to your code.

  6. rxraza

    I have done all three items as you have laid out.

    Yeah the install function is being fired. Please see the code below that I put in the bottom of the NativeControls.js file

    NativeControls.prototype.setStatusBarVisibilty = function(bHide)
    {
    cordova.exec(“StatusBar.setHidden”,bHide);
    }

    /*
    if(!window.plugins)
    window.plugins = {};

    window.plugins.nativeControls = new NativeControls();
    */

    NativeControls.install = function() {
    alert(‘installing’);
    if ( !window.plugins )
    window.plugins = {};
    if ( !window.plugins.NativeControls ) {
    window.plugins.nativeControls = new NativeControls();
    }
    alert(‘installed’);
    }
    Cordova.addConstructor(NativeControls.install);

    • Hmm well then let’s focus on your original statement about the createTabBar. We need to see if the xCode side of stuff is triggering. Find the same function in the .m file and put DLog(@”Message”) statements in the code to continue troubleshooting as you’ve done with alert statements.

      (Off to bed now, but will check this in the morning. Good luck!)

  7. rxraza

    By the way I am using Cordova 1.5.0.

  8. rxraza

    Thanks for the help so far. Ok I put some printf statements in the *.m file. Please see below. I do not see those print messages in the output console

    – (void)createTabBar:(NSArray*)arguments withDict:(NSDictionary*)options
    {
    printf(“createTabBar start”);
    tabBar = [UITabBar new];
    tabBar.autoresizingMask = UIViewAutoresizingFlexibleBottomMargin | UIViewAutoresizingFlexibleTopMargin | UIViewAutoresizingFlexibleWidth;
    [tabBar sizeToFit];
    tabBar.delegate = self;
    tabBar.multipleTouchEnabled = NO;
    tabBar.autoresizesSubviews = YES;
    tabBar.hidden = YES;
    tabBar.userInteractionEnabled = YES;
    tabBar.opaque = YES;
    self.webView.superview.autoresizesSubviews = YES;

    /* Styling hints REF UIInterface.h

    tabBar.alpha = 0.5;
    tabBar.tintColor = [UIColor colorWithRed:1.000 green:0.000 blue:0.000 alpha:1.000];

    */

    [self.webView.superview addSubview:tabBar];
    printf(“createTabBar end”);
    }

  9. rxraza

    I think that it is not able to locate the plugin. I have the following key value pair in Cordova.plist defined but it is not picking it up

    “NativeControls”, “NativeControls”

  10. rxraza

    Or Maybe it is able to locate the plugin but not triggering any of the functions from it.

  11. rxraza

    On a different note if I put print statements in a function in *.m file, would it appear in the console?

  12. rxraza

    I got it working by doing the following

    In NativeControls.js file I had the following

    NativeControls.prototype.createTabBar = function() {

    cordova.exec(“NativeControls.createTabBar”);

    };

    I replaced cordova.exec(“NativeControls.createTabBar”); with Cordova.exec(“NativeControls.createTabBar”);

    AND THAT GOT IT WORKING !

  13. Oh yeah, I heard in the latest version of Cordova, they changed from cap C to lower case, or something like that. I haven’t upgraded yet… but that makes sense man. Glad you figured it out. Probably saved me a lot of work here this weekend as well, so thanks in advance!

  14. Hello i only get one tab working,the other doesnt respond:

    //declaramos una barra
    tabBar.createItem(“contacts”, “Unused, iOS replaces this text by Contacts”, “tabButton:Contacts”, {
    onSelect: function() {
    location.href=”img/12.jpg”;
    }
    });
    //fin de la barra

    tabBar.createItem(“recents”, “Unused, iOS replaces this text by Recents”, “tabButton:Recents”, {
    onSelect: function() {
    alert(“Recents tab selected”);
    }
    });

    What can i am doing wrong?

Leave a Reply

© 2012 zSprawl's zApps

Fork me on GitHub