For the update to the RunPee app I needed to create a component to let me scroll through a series of icons that when pressed would take the user to a new screen – or some other action. You can think of it as turning a <ViewNavigatorApplication> into a <TabbedViewNavigatorApplication> that has a scrolling tab. Here’s what I came up with on the right. If you want you can download the FXP/APK file here or if you just want to install the app on your Android phone to test drive it you can download the APK here: polyGeek.com/air/ribbon.apk
Ribbon Features
- Display list of icons for navigational purposes
- Easy to customize for specific apps
- Remembers the scroll position when screen changes
- Shows the current screen that is viewed
- Scroll arrows on left/right are only displayed if there is room to scroll in that direction
- Pressing icon may lead to another screen or any other action
The source code contains both an MXML and ActionScript ItemRenderer. I always start projects like this with MXML ItemRenderers and work on it until I’m happy with how it looks and feels. Then I make an optimized ActionScript version.
I’ve seen ribbon navigation like this in other apps – WeatherBug comes to mind. I hope users like the UX. I would love to hear from you if you have an opinion on the UX or anything else regarding the <Ribbon>
Code Overview
It’s every easy to add the <Ribbon> to any screen in your app. In the sample app each screen just has the following code:
<custcomps:Ribbon navigator="{ navigator }" bottom="0" />
The real work will be in modifying the code inside the <Ribbon> component to work with your icons and your screens. You’ll want to start by modifying the RibbonBtn_rend to display your icons and the states used to select which icon is in view. I created a static constant for each <state> so that I wouldn’t have to worry about tracking down typos and such when using the state-names in other parts of the code.
Once you have the icons and states set up you just need to modify theĀ ArrayList in the Ribbon.mxml file to display all of your icons.
_iconList.addItem( { icon: RibbonBtn_rend.YOUTUBE } );
When an icon is pressed it simply runs through a series of if-else statements to determine which action to take. Usually this will be a navigator.pushView( … ) but it could be anything else. For instance in the RunPee app some of the icons open windows in the native browser.
Ribbon Navigation in action
Swipe
I didn’t really see the need to have a software-back-button since at any time you can navigate to any screen. But I did enable the swipe from left-to-right to work as a back-button-press. That also created the need for a little work around. I noticed that sometimes when sliding the <Ribbon> around it would be detected as a swipe. Here’s the code I used to solve that.
private function onSwipe( e:TransformGestureEvent ):void {
// This will let the user swipe left-to-right to return to the previous screen
// but ignore any swipes at the bottom of the screen which can be confused with
// horizontal scrolling on the Ribbon.
if( e.offsetX == 1 && e.stageY < stage.height - 100 ) {
navigator.popView();
}
}
All I’m doing is making sure that the swipe gesture didn’t happen near the bottom of the screen where the <Ribbon> is located.
Here’s the code to create the listener that should be added in the viewActivate handler.
Multitouch.inputMode = MultitouchInputMode.GESTURE; this.addEventListener( TransformGestureEvent.GESTURE_SWIPE, onSwipe );
And don’t forget to remove the event listener in the viewDeactivate handler.
private function onViewDeactivate():void {
this.removeEventListener( TransformGestureEvent.GESTURE_SWIPE, onSwipe );
}
Hack
One thing that I’ve had trouble with before is how to scroll a <List> to a specific place. The issue here is that I want the <List> to appear in the same position from screen to screen. If I user scrolls over and then taps an icon it will take them to another screen – usually – then rebuild the <Ribbon> and scroll it over to the same place it was on the previous screen.
Sounds like it should be easy but I’ve not found any event that fires after the <List> is rendered. The hack that I’ve used is to set a timer to wait 33 milliseconds and then set the scroll position which works fine. If you know of an event that fires after everything is rendered please let me know in the comments.
Note: I just updated the <Ribbon> by adding 3 new icons to display and it only took about 5 minutes to modify all the code to work correctly with the new screens and icons. So once you have it working in an app it should be quick and easy to modify.
Feedback
I’ve tested this on my Nexus One. The UX and performance seem just fine. I’d love to hear from anyone who can try this out on an iPhone 4 and see how it feels. Particularly are the icons large enough to see and touch.
I looked through the documentation and could not find anything that would enable scrolling on the <TabbedViewNavigatorApplication>. Please let me know if I missed something and it is possible.
Note: I just noticed that using a “back” navigation doesn’t highlight the newly selected icon when using the ActionScript ItemRenderer but it does work when using the MXML ItemRenderer. I’ll look into that.





I’ve used the update_complete event to scroll a list after it is set up.
“Dispatched when an object has had its commitProperties(), measure(), and updateDisplayList() methods called (if needed).”
@Dimitri Well, that didn’t really work. onUpdateComplete I’m setting the scroll position – ribbonListLayout.horizontalScrollPosition. The problem is that it fires as I’m scrolling the list sometimes. It’s sporadic.
That’s fantastic! Reminds me of the menu in the Amazon app store app Thanks for sharing.
@Mikeciz Cool, if Amazon uses it then the UX must have past a lot of usability tests. I feel better about using it now. Thanks.
Really nice post. I’ve tested it with my HTC Desire and works great, thanks!
Wow, this is great. I was looking for something similar that I’m going to use in a app I’m working on.