[Product update] Infrastructure Analysis Tool is now available with Business Accounts.Learn More


Appcelerator: Making an expandable (accordian) menu

Published on
5,402 Points
1 Endorsement
Last Modified:
Preface: This article is part of a series focused on cross platform mobile app development (specifically Android and iOS) using the Alloy framework and Titanium Studio made by Appcelerator. This article presumes a working knowledge of Titanium Studio and the Alloy framework.

The Alloy framework has great built in elements for making a simple menu, mainly using the TableView (and TableViewRow) system. Unfortunately this does not include any built in functionality for expanding and collapsing rows. At first glance, using the "insertRowAfter" and "deleteRow" methods of the TableView would work for this. Unfortunately there seems to be a bug with the iOS implementation which leads to a "no row found for index" error when deleting rows. To avoid this error, the menu can be implemented as verticaly aligned View elements.

In the menu View elements represent each row. The rows for the submenus start out "hidden" by a wrapper View with a height of 0. Each row of them menu that does not expand will have a "menuAction" property which will be harvested by the "menuClick" onClick listener. The parent row of each submenu will have extra properties which define how big the submenu is and the name of the submenu's wrapper View.

Example Alloy markup would look like this:

file: /views/index.xml
  <Window class="container">
    <ScrollView id="menu" layout="vertical">
      <View class="menuDivider"/>
      <View class="menuRow" onClick="menuClick" menuAction="home">
        <Label class="rowName">Home</Label>
      <View class="menuDivider"/>
      <View class="menuRow" onClick="menuClick" menuAction="away">
        <Label class="rowName">Away</Label>
      <View class="menuDivider"/>		
      <View class="menuRow" onClick="menuExpand" menuItems="3" submenuId="submenuBrowsers" expanded="false">
        <Label class="rowName">Browsers</Label>
        <Label class="expandArrow" id="expandIndicator" text=">"/>
      <View class="submenuWrap" id="submenuBrowsers" layout="vertical">
        <View class="menuDivider"/>
        <View class="submenuRow" onClick="menuClick" menuAction="chrome">
          <Label class="rowName">Chrome</Label>
        <View class="menuDivider"/>
        <View class="submenuRow" onClick="menuClick" menuAction="firefox">
          <Label class="rowName">FireFox</Label>
        <View class="menuDivider"/>
        <View class="submenuRow" onClick="menuClick" menuAction="ie">
          <Label class="rowName">Internet Explorer</Label>
      <View class="menuDivider"/>
      <View class="menuRow"  onClick="menuExpand" menuItems="4" submenuId="submenuPhones" id="network" expanded="false">
        <Label class="rowName">Smart Phones</Label>
        <Label class="expandArrow" id="expandIndicator" text=">"/>
      <View class="submenuWrap" id="submenuPhones" layout="vertical">
        <View class="menuDivider"/>
        <View class="submenuRow" onClick="menuClick" menuAction="android">
          <Label class="rowName">Android</Label>
        <View class="menuDivider"/>
        <View class="submenuRow" onClick="menuClick" menuAction="blackberry">
          <Label class="rowName">Blackberry</Label>	
        <View class="menuDivider"/>
        <View class="submenuRow" onClick="menuClick" menuAction="iphone">
          <Label class="rowName">iPhone</Label>
        <View class="menuDivider"/>
        <View class="submenuRow" onClick="menuClick" menuAction="windows">
          <Label class="rowName">Windows</Label>
      <View class="menuDivider"/>
      <View class="menuRow" onClick="menuClick" menuAction="settings" id="bottom">
        <Label class="rowName">Settings</Label>

Open in new window

The "tss" (Titanium Style Sheet) file specifies the initial styles of the menu. Note the "submenuWrap" has a height of "0" and visible set to "false". Each submenu row is configured to have a height of "36".
file: /styles/index.tss
".container" : {
   backgroundColor: "#63666a"
"#menu" : {
   backgroundColor: "#63666a",
"Label" : {
   color: "#fff",
   height: Ti.UI.FILL,
   touchEnabled: "false"
".menuDivider" : {
   width: Ti.UI.FILL,
   height: '1dp',
   backgroundColor: '#999'
".menuRow" : {
   height: '40dp',
   backgroundColor: '#777',
   width: Ti.UI.FILL
".rowName" : {
   left: '20dp'
".expandArrow" : {
   right: '20dp'
".submenuWrap" : {
   height: '0dp',
   visible: 'false'
".submenuRow" : {
   height: '36dp',
   backgroundColor: '#888'

Open in new window

The controller is where the expanding and collapsing is processed. When a submenu's title row is clicked, the "expandMenu" function will calculate how tall to make the submenuWrap View so that the submenu will be visible. To collapse the menu the submenuWrap is set back to a height of "0". Note: Each row in the menu includes a "divider" which is a height:1 View, hence why the value used to calculate the new height is 37 for each row instead of 36.
file: /controllers/index.js
function menuClick(e) {
   //  Perform processing based on the menuAction of the clicked menu item

var submenuRowHeight = 37;

function menuExpand(e) {
   var menuRow = e.source;
   var submenuWrap = $[menuRow.submenuId];
   if (menuRow.expanded == 'false') {
      var newHeight = (submenuRowHeight * menuRow.menuItems);
      menuRow.expanded = 'true';
   } else if (menuRow.expanded == 'true') {
      menuRow.expanded = 'false';


Open in new window

This is a basic example of a menu that includes optional expanded submenus created in the Alloy framework that will work for both Android and iPhone devices. The nested submenu items could also be have their own submenus allowing for deeper navigation. By incorporating this menu into an app it can be utilzied as a "side swipe" drawer, options list, or any number of uses.
Author:Mark Olsen

Featured Post

Exploring ASP.NET Core: Fundamentals

Learn to build web apps and services, IoT apps, and mobile backends by covering the fundamentals of ASP.NET Core and  exploring the core foundations for app libraries.

Join & Write a Comment

Please check the video also in regards to recovery of deleted emails from office 365 admin center and through the MFCMAPI tool. I have mentioned each and every step with the proper steps that need to be taken care of.
I've published three five-minute Experts Exchange video Micro Tutorials that describe terrific features in an excellent, free PDF product called PDF-XChange Editor: How to rotate pages in a PDF with free software (https://www.experts-exchange.com…
Other articles by this author

Keep in touch with Experts Exchange

Tech news and trends delivered to your inbox every month