Ordering from a menu
you haven’t seen before.
So you’re an iOS developer looking to get into the exciting world of Android development! Or at least I was a few weeks ago, and I was excited to hear my newest assignment at Ellipsis Digital was to create an Android sibling to my latest iOS app.
My name is James Harquail, mobile developer mediocaire. I say that not to fish for compliments, but more because despite my experience, I am continuously excited and baffled by what mobile development has to offer. I have worked almost exclusively on iOS apps, with the odd foray into Android to do light bug fixes and updates, but over the last few years it has become harder and harder to ignore the growing popularity of Android. I was finally offered the rare privilege that every developer loves: getting paid to learn something new.
So, let’s skip the basics. I won’t walk through all the ins and outs of Android (you can find that in the Android Developer's Guide). I will assume you have a working knowledge of iOS, and have installed Android Studio and at least done a “Hello World” activity.
(Still feels pretty good seeing those words for the first time on a new platform, doesn’t it?)
For this article, I wanted to go over an interesting problem that arose from the fundamental differences between the ways that iOS and Android manage navigation.
Let’s take a look at a very familiar app structure, what is commonly called a “burger and basement”. If you haven’t heard of it before don’t worry, you’ve definitely seen it. The menu button and sliding options list has become the most popular way to show a menu on mobile devices (and recently, for some reason, on the Web as well). The burger part of the name obviously comes from the single-patty sandwich that represents “Menu”, and the basement aspect comes from the fact that burgers could only be served in underground speakeasies during the beef-prohibition era of the early 2000’s.
Have It Your Way: iOS
Here is how I would create the menu in iOS. I start with a parent UIViewController that will manage the view hierarchy and handle switching between the different menu options.
The first view element to be added is a UITableViewController that will act as the basement menu. On top of that I add a UINavigationController that acts as the core navigation structure of the app. We need to consider two use cases for handling menu navigation.
The first is the obvious menu selection from the basement. In this case, we want to replace any currently displayed views with the selected menu option. If the user is currently on the selected view, we can simply ignore the menu selection and close the basement.
The second case is if the user selects a link in a view instead of from the basement menu. An example can be found in the image below. If the user selects the “Get Help” button from the Dashboard on the left instead of the menu option on the right, we will push the new view onto the stack instead of replacing it entirely. Because we used a child Navigation Controller to handle the structure of the app, this can simple be done inside the Dashboard View Controller by calling self.navigationController.pushViewController: animated:, as expected. This way is ideal because it will follow the typical app design standards, sliding the view in from the right and showing the default back button as expected.
View Structure for the Be Safe app. I also included a UIView above the navigation controller to darken the current view and catch any close gestures.
Android: I’m Lovin’ It
So we have created an easy burger/basement implementation in iOS, now to figure out how to recreate it in Android. Android has a slightly different method of handling navigation and views. Instead of a central Navigation Controller, views are managed using Activities and Intents.
Activities are individual views based around a set of actions a user can perform. Each Activity is presented using Intents, a call to the Android device to add a new Activity to what is called the “back stack”. This represents one of the core differences between the systems. Where iOS devices only have a Home button to return the user to the home screen, Android devices also include a dedicated back button. When the user presses this button, it pops the current Activity from the stack, and returns the user back one level. Press it enough times, and you are returned to the home screen.
Now we get to the crux of the problem when we try to recreate the burger menu in Android.
If we followed the same development principles as iOS, each app screen should have a view and a controller to manage it. With the burger menu included, we would need to create a separate identical menu for each Activity we create for the app in Android. Luckily there is an easy solution introduced in the Honeycomb update: fragments. Fragments act identically to a child View Controller in iOS, allowing developers to easily abstract common elements and add multiple Fragments to each Activity. Following the Android example DrawerLayout code, we can see that it includes two components: a FrameLayout that will act as the content view as our Navigation Controller did in iOS, and a ListView that will be our equivalent menu table.
<android.support.v4.widget.DrawerLayout xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/drawer_layout" android:layout_width="match_parent" android:layout_height="match_parent"> <!-- The main content view --> <FrameLayout android:id="@+id/content_frame" android:layout_width="match_parent" android:layout_height="match_parent" /> <!-- The navigation drawer --> <ListView android:id="@+id/left_drawer" android:layout_width="240dp" android:layout_height="match_parent" android:layout_gravity="start" android:choiceMode="singleChoice" android:divider="@android:color/transparent" android:dividerHeight="0dp" android:background="#111"/> </android.support.v4.widget.DrawerLayout>
Default Android implementation of a Menu Drawer
Now that we have defined our Main Activity, we need to handle the same two use cases as the iOS app.
The first case, where the user selects a menu option, is easy. We take a reference to the the main content view (in this example, it has the id “content_frame”), and user a FragmentManager to swap in different Fragments depending on what menu option was selected.
FragmentManager fragmentManager = getSupportFragmentManager(); fragmentManager.beginTransaction() .replace(R.id.content_frame, *New Fragment*) .setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN) .commit();
But this will not work for our second use case, where the user selects a link from a view instead of the basement menu. If the user navigates through the app, they should be able to backtrack by using the Android back button, otherwise we will not be providing the expected UX behaviour. Unlike iOS, we will need to include a few separate methods in the parent Activity. One will handle resetting the view stack, used when selecting a menu option. The other will simple push a new Fragment on the stack, which will be popped when the back button is pressed. Using the same Fragment Manager as before, we can easily change it to do this by calling .add() instead of .replace(). (Pay attention to the .addToBackStack call, it is what will add the transaction to the back stack.)
fragmentManager fragmentManager = getSupportFragmentManager(); fragmentManager.beginTransaction() .add(R.id.content_frame, *New Fragment*) .setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN) .addToBackStack(*Fragment Name*) .commit();
Now we have a simple basement drawer in Android that follows the expected UX and uses the simple default implementation. It even automatically creates a burger menu with a snazzy default opening and back animation. You should now be able to easily add new Fragments to your projects and link to them from the Main activity.
So there you have it—my first bites into programming for Android after years feasting on iOS. It’s been as exciting a learning experience as I hoped and I’m looking forward to learning more as we continue to iterate this app and others we’ve got in the works.
Check out the app described in this article on both the Apple and Android stores.
James Harquail is Ellipsis Digital’s mobile developer and we’re as excited as he is to dig deeper into all that mobile has to offer.