Appcelerator Blog

The Leading Resource for All Things Mobile

A cross platform navigation group

0 Flares 0 Flares ×

There are many differences between iOS and Android, but perhaps one of the most noticeable is iOS’ Navigation Group. This control is a fundamental part of iOS and a very useful and easy to implement navigation paradigm. It conforms to iOS’ design guidelines and provides you a “free” way of going back to your previous screen.

However, when you are developing a cross-platform app, you soon realize that there’s no equivalent on Android, or I should say, there wasn’t one until Android 3.0. If you’re not an Android user, you probably haven’t noticed, mainly because when you create an Android App on Titanium it defaults to API Level 8 (Android 2.2 Froyo), the second most used Android version in the world. If you run a default Android App it will look something like this.

The window on this app is basic, simple, with a thin titlebar with no room to add your navigation button. The workaround I often see is to use views to simulate iOS’ titlebar and back button, and although this solves the problem, leads to an Android app that looks like an iOS app.

In mid 2011 Android 3.0 was released and with it, a brand new UI named Holo, which provides a more mature and standardized way of approaching Android user interfaces. One of the components of Holo is the ActionBar, and this component allows us to provide the same navigation paradigm as the Navigation Controller.

To use the ActionBar on your app, you need to tell Titanium to use and Android API that has these features. The one I use is API Level 14, which corresponds to Android 4.0. To change this, go to your tiapp.xml, scroll to the Android section and inside the android tag add:

14

This tells Titanium that to use the API from Android 4.0 (Ice Cream Sandwich). Then, to use the ActionBar add this also to the Android section:


	

This sets an Android pre-defined theme. The Theme could be any of the following:

@android:style/Theme.Holo
@android:style/Theme.Holo.Light
@android:style/Theme.Holo.Light.DarkActionBar

Now if you run the same simple app, you’ll see that it now looks like any other modern Android app.

I’ll explain more about the ActionBar in a future blog post.

Using Alloy Magic

This can also be accomplished using Titanium Classic syntax, but with Alloy is much easier. I have created a simple template app for you to use, experiment with and expand, but the real heavy lifting is performed by a small function I call openWin. This function is essentially a cross-platform window opener, which receives a pointer to the iOS Navigation Group and the name of the view file to open. If running on iOS, it opens the view as a new child of the Navigation Group. If running on Android, it simply pays no attention to the Navigation Group and creates a new activity with an up button and an event handler to close the activity.

exports.openWin=function(navGroup,winName){
	var w=Alloy.createController(winName).getView();

	if (OS_ANDROID){
		w.addEventListener('open',function(e){
			if (! w.getActivity()) {
	            Ti.API.error("Can't access action bar on a lightweight window.");
	        } else {
	            actionBar = w.activity.actionBar;
	            if (actionBar) {
	                actionBar.displayHomeAsUp=true;
	                actionBar.onHomeIconItemSelected = function() {
	                    w.close();
	                };
	            }
	            w.activity.invalidateOptionsMenu();
	        }
		})
		w.open();
	}else{
		navGroup.open(w,{animated:true});
	}
}

Here’s a video of how it looks and behaves, running on Android 4.1, iOS6 and iOS7, all from the same source code.

Notes: By using API Level 14, you’re actually limiting your target users to only those with an Android 4.x device. You could use API Level 11 and target all devices since 3.0, but in this case you’ll have no access the Holo.Light.DarkActionBar theme. More about API Levels at http://developer.android.com/guide/topics/manifest/uses-sdk-element.html.

Devices with Android 2.x have no access to the ActionBar. For these devices I suggest you use the ActionBarClone Alloy Widget that will bring an emulated ActionBar on any Android version.

0 Flares Twitter 0 Facebook 0 Google+ 0 LinkedIn 0 Email -- 0 Flares ×

28 Comments

  1. Pascal

    Hello,

    I have an issue on android.
    It works well with SKD 3.1.1GA but it doesnt with 3.1.2GA.
    Sometimes two ActionBar are displayed verticaly.

    Pascal.

    • Ricardo Alcocer

      Hi Pascal,

      You’re right, there’s an issue with a double ActionBar in 3.1.2GA. This was already fixed..here’s the ticket: https://jira.appcelerator.org/browse/TC-2795

      R

  2. Great article!

    Your tips are the best.

  3. Mark

    And if Titanium implemented the new Action Bar support library, we can have Action Bar on all Android versions
    http://www.youtube.com/watch?v=6TGgYqfJnyc
    There is an open ticket on it, would be awesome if completed:
    https://jira.appcelerator.org/browse/TIMOB-15021

  4. Very interesting info. Will definitely us API level 11 so that older Android versions could be supported in my app, that was developed using C2Call video chat SDK (https://www.c2call.com)

  5. DHennrich

    I’m trying to use the classic syntax of titanium to use navigation on android but I don’t know how to do that…
    can you give a sample of this cross-platform navigation group?

    and with the change of navigation on new version of Titanium 3.1.3 will have some issue with your code?

    Thanks

    • Ricardo Alcocer

      Hi DHennrich,

      Classic is very different so it requires some changes. Please take a look at this Gist with a demo of how to achieve the same results using Classic syntax. https://gist.github.com/ricardoalcocer/6512574

      R

      • Frankie P

        Your “Titanium Classic version at..”-link is not working and referring to the same Alloy code ? In your Gist response to DHennrich I’m seeing first line that requires /lib/xpngclassic, but I can’t find xpngclassic.js in the code.
        For newbees and none-Alloy users (like me) that is confusing. Would you please cough up the Classic version as well ? Or tell a bit more how to use this for none-Alloy? Thanks.

        • Ricardo Alcocer

          Hi Fankie P, thanks for spotting this. I’ve updated the repo and it now includes a TiClassic folder with a full Titanium Classic example. I also updated the xpng.js lib to accept the “payload” argument in Ti Classic. You can find everything over at https://github.com/ricardoalcocer/TiCrossPlatformNavigationGroup

          Hope this helps!

          R

          • Frankie P

            Working now. Thanks a lot!

  6. DHennrich

    Thanks Ricardo!

    It’s very very very useful

    Thank you very Much

    By the way… through your video I can see that on the new version of Titanium it will work too.

  7. Nuno Castelinho

    Is it possible to add a navigation drawer? It’s a shame that the actionbar doesn’t have this feature.

  8. Good tips. For Android 4 is perfect.

    For a easy to use Crossplatform Navigation Group for both, iOS and Android, using version 2.2, I’ve recently leave this in my GitHub

    https://github.com/mcvendrell/Basic-custom-NavBar

    You have a complete demo there and some screenshots.

  9. I have my own version of a cross platform Navigation Group. It doesn’t have the Android ActionBar, but it’s another option for folks out there. And it’s written in Alloy.

    https://github.com/vuinguyen/NavControlAlloy

    Feel free to fork from this project. Enjoy!

  10. Emre

    Does this really work with Titanium 3.1.3? I just tried it out for android (cloned your git repo) and after clicking on the first button ‘Open blue window’ I’m getting this exception:

    [ERROR][TiApplication( 1517)] (main) [317,5971] Sending event: exception on thread: main msg:java.lang.NullPointerException; Titanium 3.1.3,2013/09/18 12:01,222f4d1
    [ERROR][TiApplication( 1517)] java.lang.NullPointerException
    [ERROR][TiApplication( 1517)] at org.appcelerator.titanium.proxy.ActionBarProxy.handlesetDisplayHomeAsUp(ActionBarProxy.java:178)
    [ERROR][TiApplication( 1517)] at org.appcelerator.titanium.proxy.ActionBarProxy.handleMessage(ActionBarProxy.java:201)
    [ERROR][TiApplication( 1517)] at android.os.Handler.dispatchMessage(Handler.java:95)
    [ERROR][TiApplication( 1517)] at android.os.Looper.loop(Looper.java:137)
    [ERROR][TiApplication( 1517)] at android.app.ActivityThread.main(ActivityThread.java:4745)
    [ERROR][TiApplication( 1517)] at java.lang.reflect.Method.invokeNative(Native Method)
    [ERROR][TiApplication( 1517)] at java.lang.reflect.Method.invoke(Method.java:511)
    [ERROR][TiApplication( 1517)] at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:786)
    [ERROR][TiApplication( 1517)] at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:553)
    [ERROR][TiApplication( 1517)] at dalvik.system.NativeStart.main(Native Method)
    [ERROR][AndroidRuntime( 1517)] FATAL EXCEPTION: main
    [ERROR][AndroidRuntime( 1517)] java.lang.NullPointerException
    [ERROR][AndroidRuntime( 1517)] at org.appcelerator.titanium.proxy.ActionBarProxy.handlesetDisplayHomeAsUp(ActionBarProxy.java:178)
    [ERROR][AndroidRuntime( 1517)] at org.appcelerator.titanium.proxy.ActionBarProxy.handleMessage(ActionBarProxy.java:201)
    [ERROR][AndroidRuntime( 1517)] at android.os.Handler.dispatchMessage(Handler.java:95)
    [ERROR][AndroidRuntime( 1517)] at android.os.Looper.loop(Looper.java:137)
    [ERROR][AndroidRuntime( 1517)] at android.app.ActivityThread.main(ActivityThread.java:4745)
    [ERROR][AndroidRuntime( 1517)] at java.lang.reflect.Method.invokeNative(Native Method)
    [ERROR][AndroidRuntime( 1517)] at java.lang.reflect.Method.invoke(Method.java:511)
    [ERROR][AndroidRuntime( 1517)] at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:786)
    [ERROR][AndroidRuntime( 1517)] at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:553)
    [ERROR][AndroidRuntime( 1517)] at dalvik.system.NativeStart.main(Native Method)

    I tried it out for Android 4.0.3 and 4.3..

    Any advices here?

  11. Ricardo Alcocer

    Hi Emre,

    I just re-downloaded the repo and ran it on a Galaxy S4 with 4.2.2 stock and it does work. Did you try on device or emulator?

    R

  12. Emre

    hi Ricardo,

    I did it inside my emulator, have I missed a warning for not using it inside emulators somewhere?

    cheers and thanks
    emre

  13. Michael Stelly

    Demo app works fine in iOS 7.x simulator. Android emulator crashes when launching with this error:

    [ERROR] : Emulator process exited with code 1
    [ERROR] : Build process exited with code 1
    [ERROR] : Project failed to build after 495ms
    [ERROR] Application Installer abnormal process termination. Process exit value was 1

    Using android 4.4, WXGA800 screen. I don’t know how to fix this error, so cannot get code to run.

    • Ricardo Alcocer

      @Michael, what version of Titanium SDK are you compiling with? Do you also have Android 2.3.3 installed?

      • Michael Stelly

        Hi Ricardo,
        Here are my stats:
        – app: android mobile
        – android sdk: 4.4
        – Ti SDK 3.1.2
        – os: osx mavericks
        – studio Titanium Studio, build: 3.1.3.201309132423
        – output: Android emulator WXGA800 7in tablet

        • Ricardo Alcocer

          Are you able to run other Android projects? This appears to be related to Android configuration. With 3.1.x you also need to have installed Android SDK 3.2.2, so make sure you also have it installed.

          • Michael Stelly

            Ricardo,
            Unless I missed something, there is no android 3.2.2. Did you mean 2.3.3 (API10)? I have that installed. And yes, I am able to launch other android apps with the emulator.

          • Ricardo Alcocer

            Have you tried running the sample app on any other Android? I haven’t tested on 4.4 yet.

          • Michael Stelly

            Haven’t had time to check. I’ll post the results when I do.

            Thanks.

  14. Ravi

    Hi, am new to android ,currently am learning titanium with classic
    i need how to implement the desight
    how to run in emulator?
    can you help me friends..

Comments are closed.

Sign up for updates!

Become a mobile leader. Take the first step to scale mobile innovation throughout your enterprise.
Get in touch
computer and tablet showing Appcelerator software
Start free, grow from there.
0 Flares Twitter 0 Facebook 0 Google+ 0 LinkedIn 0 Email -- 0 Flares ×