iOS SDK: Creating a Custom Accordion Menu

This tutorial will teach you how to create a custom Accordion Menu. This animated menu will allow you to collect input from the user in an engaging and streamlined fashion. Read on to learn more!


Tutorial Preview


About the Accordion Menu

The accordion menu's initial position will be at the center of the target view it appears on. When the menu appears, half of it will move towards the top of the target view, while the other half will move towards the bottom of the view, expanding to its full allowed height. During use, both the Y origin point and the height are going to be modified so that the desired effect can take place. The menu itself will consist of a tableview. It will provide us with great flexibility regarding the number of options added to the menu. The tableview is going to exist as a subview on a view and will appear on a target view. The main view of the accordion menu's view controller will work as a cover to the subviews existing at the back, so the user is unable to tap on anything else except for our menu options.

Let's go ahead and bring this idea to life. Here's an image of what the final product will look like.

final_accordion_menu

1. Create the Accordion Menu View Controller

Step 1

The first thing we must do is create a new view controller for our accordion menu. Prior to that, we'll create a new group in the Xcode to keep everything neat and tidy.

In the Project Navigator pane on the left side of the Xcode, Control + Click (right click) on the CustomViewsDemo group. Select the New Group option from the popup menu.

create_group_2

Set Accordion Menu as the name.

group_name_2

Step 2

Let's create the view controller now. Control + Click (right click) on the Accordion Menu group. Select the New File... option from the popup menu.

create_file_2

Select the Objective-C class as the template for the new file and click next.

new_file_template_2

Use the name AccordionMenuViewController in the class field and make sure that in the Subclass of field the UIViewController value is selected. Don't forget to leave the "With XIB for user interface" option checked.

accmenu_view_controller

Finally, click on the create button. Make sure that the Accordion Menu is the selected group, as shown in the next image.



2. Configure the interface

The first thing we need to do with our new view controller is setup the interface in the Interface Builder, which should be pretty simple. Most of the work will be done in code.

Step 1

Click on the AccordionMenuViewController.xib file to turn the Interface Builder on. Click on the default view and turn the Autolayout feature off so it works on versions of iOS prior to 6.

  • Click on the Utilities button at the Xcode toolbar to show the Utilites pane if it is not visible.
  • Click on File Inspector.
  • Scroll towards the bottom a litte bit and click on the "Use Autolayout" option to turn it off.
autolayout_2

Next, go to the Attributes Inspector. In the Simulated Metrics section, set the Size value to None so that it will work on a 3.5" screen as well.

view_size_2

Step 2

Go ahead and add a new view, but make sure that you don't add it as a subview to the default view. Do the following:

  • Go to the Simulated Metrics section of the Attributes Inspector and set the Size to None.
  • Change the background color to dark grey.
second_view_config

Step 3

Grab a tableview from the Object Library and add it as a subview to the view we added in the previous step. Complete the next configuration in the Attributes Inspector section.

  • Set Shows Horizontal Scrollers to off.
  • Set Shows Vertical Scrollers to off.
  • Set Scrolling Enabled to off.
  • Change the background color to clear.
tableview_options

This is what your interface should look like at this point.

ib_sample_2

3. Set the IBOutlet Properties

Step 1

Next, we're going to create two IBOutlet properties for the extra view and the tableview we added to the project earlier. First, we should make the Assistant Editor appear. Click on the middle button in the Editor section on the Xcode toolbar to reveal it.

assistant_editor2_1

Step 2

To connect the view to a new IBOutlet property, go to Show Document Outline > Control + Click (right click) > New Referencing Outlet. Drag and drop into the Assistant Editor.

insert_outlet_2

I named the property viewAccordionMenu and I recommend that you use the same name to avoid any problems while coding. Set the Storage option to Strong instead of the default Weak value.

iboutlet_name_2

Step 3

Now let's add an IBOutlet property for the tableview. Just as we did above, create a new property named tblAccordionMenu. Set the Storage option to Strong as well.

Here are the two IBOutlet properties.


4. Do Some Code Level Setup

So far so good! We've created the view controller for the accordion menu, we've setup the interface, and we've created the two required IBOutlet properties for the views we added to the builder. Now it's time to begin writing some code.

Step 1

First of all, we should set our view controller as the delegate and datasource of the tableview we created in the Interface Builder. Our view controller should adopt the respective protocols. Click on the AccordionMenuViewController.h file and right next to the @interface header add the following.

Step 2

Click on the AccordionMenuViewController.m file and implement a simple init method. Set the view controller as the delegate and datasource of the tableview.

To make the menu look better, let's add a border. In the init, add the highlighted code.

Make sure to add this to the top of the file.

Set the background color of the default view to light grey with transparency.

Step 3

It's a good idea to define the row height of the tableview as a constant. Apart from the tableView:heightForRowAtIndexPath method, we are going to use it in other methods. Right after the #import commands, add the following.

The accordion menu will use animation to appear and disappear. We can set the duration of the animation as a constant.

From now on, if we want to change the row height or the animation duration we'll do it once without changing the values in each method.

Step 4

We should declare two private variables and an NSArray. The variables regard the accordion menu width and height, meaning the width and height of the parent view of our tableview. The NSArray is the array that will keep the menu options, and it will be the datasource of the tableview.

At the top of the AccordionMenuViewController.m file add the next lines in the @interface section.

Make sure you don't forget the curly brackets!


5. Implement the Public Methods

There are at least three public methods that should be implemented in order for the accordion menu to work properly. The first method will be used to set the options of the menu, the second method will make the accordion menu appear, and the third method will make it disappear.

Step 1

First of all, we should declare the methods I mentioned above into the .h file. So, click on the AccordionMenuViewController.h file and add the following.

Step 2

Let's implement the first method. Click on the AccordionMenuViewController.m file and write or copy/paste the following code.

Even though this is a really simple method, let me explain it a little bit. I find it easier for the user and the programmer to provide an array with menu options only. You don't need to be concerned about the so-called close menu option. That's really only useful when someone is going to use the accordion menu in more than one case. I use the tempArray mutable array to put together both the user options and the close option. If you know that the _optionsArray is not mutable, you'll understand that it cannot accept new objects after creation. I initialize the _optionsArray array. It's your choice to avoid using this logic or change the title of the close menu option.

Step 3

Let's move on to the next method. It'll concern the way the accordion menu appears on screen. A lot of different steps take place in it, so I'll present and discuss it in parts.

First of all, we need to take the status bar under consideration when the accordion menu is about to appear. This is because we'll use the target view where the menu will appear and its frame as a base to configure our views. Thus, it's really important to handle the status bar correctly. If the status bar is hidden, there's no problem at all. If it's visible, however, an empty space equal to the status bar height will be created when we make our view appear. So, as a first step, we need to check if the status bar is visible and store its height to fix the offset created by this.

This is the approach we followed during the previous tutorial in the custom text input view.

Next, we should specify what the width and height of the target view is depending on the orientation. Depending again on the orientation, we should "tell" whether the offset that should be moved by our default view is on the X or the Y axis.

The next step is easy. We'll simply set up the default view, self.view, by setting its frame and the appropriate offset, its alpha value, and finally adding it as a subview to the target view.

Now it's time to configure the view that contains the tableview. We have to specify its size here, keeping in mind that it will occupy a portion of the screen. I set its width to 260.0 px, but you can change it according to your desires. Its height will be calculated based on the total options and the height of each row. That means that the height will be equal to the total rows multiplied by the height of each row. In the case of too many options, and a menu height greater than the target view height in either orientation, we should manually shrink the menu and enable scrolling on the tableview. To achieve that, we'll use a temporary variable that will keep the height in each case.

In order to achieve the accordion effect, we need to set its frame twice. At first, we'll give it its normal frame and we'll center it according to the target view center point. Then we'll store the Y origin point and set the frame again. We'll do this by setting the Y origin point to the Y origin point of its center and setting its height to 0.0. When the Y origin point and the height get restored to their original values, we'll have a great accordion effect.

It's time to animate the menu. There's really nothing special to discuss here. We simply change the alpha value of the self.view and set the final frame to the menu view.

Finally, reload the table data so the menu options appear on the tableview. Note that the method ends here.

Step 4

Let's write the next method regarding the menu closing. There's nothing I really need to mention here. I'll only emphasize that it uses a boolean parameter that specifies whether the closing should be animated or not.


6. Consider Orientation Changes

We've succeeded in making our menu appear correctly when called. What happens when the user rotates the device, though? Nothing! This is because we haven't written anything concerning this, so let's do it now. We'll implement the viewWillLayoutSubviews method, which gets called every time the orientation is changed. You can read more about it at Apple's developer website.

Here's the short version of what we're going to do. First, we'll set the menu view's frame, based on the menuViewWidth and the menuViewHeight variables we set earlier. We'll center it according to the self.view center point. Next, depending on the device orientation, we'll calculate the height of the superview. Finally, we'll check whether the view's height is greater than the superview's height. If that's true, we'll manually shrink it and make scrolling enabled, just like we did in the -(void)showAccordionMenuInView:(UIView *)targetView method. Otherwise, we'll simply turn scrolling off.


7. Implement the Tableview Methods

Step 1

Here are the minimum required methods needed to make the tableview work. Note that in the -(UITableViewCell *)tableView:cellForRowAtIndexPath: method, we'll check to see whether the current row is the last one or not.

Step 2

We also need to handle the tapping on the rows of the tableview. Note in the following method that we remove the selection from the tapped row.

We'll get back to this method pretty soon.


8. Protocol Definition

When the user taps on a row, or in other words a menu option, we want the caller view controller to be notified about the selected choice.

Step 1

Click on the AccordionMenuViewController.h file and write the following code, right before the @interface header.

Step 2

Now, declare a delegate property.

Step 3

When should the userSelectedOptionWithIndex delegate method be used? Every time a menu option gets selected. Go back in the -(void)tableView:didSelectRowAtIndexPath: method and add the following lines.


9. The Accordion Menu in Action

The accordion menu is now ready. It's time to see it in action. Make the required preparations in the ViewController class.

Step 1

First of all, the ViewController class should adopt the AccordionMenuViewControllerDelegate protocol. Open the ViewController.h file, import the AccordionMenuViewController.h class and add the protocol in the @interface header.

Step 2

Open the ViewController.m file and go to the private part of the @interface at the top of the file. In there, add an NSArray that will be used for the options we'll provide the accordion menu with, as well as an AccordionMenuViewController object.

Step 3

Inside the viewDidLoad method, we need to initialize both the array and the object we declared in the previous step.

We'll only use two options from the list above. For the time being, the rest are for demonstration purposes only.

Step 4

Go to the -(void)tableView:didSelectRowAtIndexPath: method and add the following.

If you're continuing the project from the previous tutorial, delete or comment out any existing content.

Step 5

Finally, we just need to implement the -(void)userSelectedOptionWithIndex:(NSUInteger)index delegate method. This is where any actions are taken when the user taps on the menu options.

We're finished! Run the app on the simulator or on a device and check out the menu. Play around with it, and don't hesitate to improve it or change it according to your needs.


Conclusion

Providing users with menu options that are different than the usual predefined ones is always a great challenge for a programmer. As you now know, we can achieve a nice result without using any difficult or extreme techniques. The accordion menu presented in this tutorial is a pretty nice way to display options to the user and, most importantly, it is reusable. I hope it will become a useful tool to everyone who uses it!

Tags:

Comments

Related Articles