quinta-feira, 31 de julho de 2014

Android Sliding Menu using Navigation Drawer

You might have noticed that lot of android applications introduced a sliding panel menu to navigate between major modules of the application. Previously this kind of UI was done using some third party libraries where a list view and some swiping gestures used to achieve this. But now android itself officially introduced sliding panel menu by introducing a newer concept called Navigation Drawer.
Most of the time Sliding Menu (Navigation Drawer) will be hidden and can be shown by swiping the screen from left edge to right or tapping the app icon on the action bar.
In this tutorial we are going to learn how to use navigation drawer to add a sliding menu to your application.




Example Applications

You can see lot of popular applications like Facebook, Youtube, Google + already introduced navigation drawer menu in their applications. Following are the navigation drawer menus of multiple apps.
android navigation drawer facebook, google plus, youtube
In order to demonstrate navigation drawer, I am taking an example of Google+ navigation drawer and explained the process to achieve the same. But before starting the project I have downloaded required icons and using photoshop I have made each icon into different dimensions for xxhdpi (144×144 px), xhdpi (96×96 px), hdpi (72×72 px) and mdpi (48×48 px) drawbles.
Also I have downloaded navigation drawer toggle icon and included in drawable folders. You can get all the images in the source code of this tutorial. We need another image to replace the action bar up icon to toggle navigation drawer. Save following images and later add them to your project.

ic_drawer.png
ic_drawer ic_drawer ic_drawer


Let’s start by creating a new project..

Starting new Project

1. Create a new project in Eclipse from File ⇒ New ⇒ Android Application Project. I had left my main activity name as MainActivity.java and gave the package name as info.androidhive.slidingmenu.
2. I prepared required string variables for List View items and icon names in strings.xml. Open your strings.xml located under res ⇒ values and add the following code.






3. Android introduced a newer UI element called DrawerLayout for Navigation Drawer. Open your layout file (activity_main.xml) for main activity and type the following code.
Here FrameLayout is used to replace the main content using Fragments and it should be always the first child of the layout for z-index purpose.





Creating Custom List View Adapter

Creating a listview with a icon, title and a counter isn’t straight forward. We have to build a custom listview to achieve this. For this I am going to create a custom adpater class for listview which provides a custom layout for individual list item in the listview.
Before start coding the custom adapter, I am going to create required layout files for the list view.
We need the layout drawables to state the list item state when normal and pressed. It needs overall three xml files. One is for normal state, second is for pressed state and third one to combine both the layouts.
4. So create a xml file under res ⇒ drawable folder named list_item_bg_normal.xml and paste the following code. (If you don’t see drawable folder, create a new folder and name it as drawable)





5. Create another xml layout under res ⇒ drawable named list_item_bg_pressed.xml with following content.






6. Create another xml file to combine both the drawable states under res ⇒ drawable named list_selector.xml






7. We need one more drawable xml for rounde corner background for the counter value. So create a xml file named counter_bg.xml under res ⇒ drawable.
If you want to know how to add a rounded corner border layout, you can learn from How to add Rounded Corner borders to Android Layout





8. As listview has the custom layout, we need another layout file which defines the each list row. So create a layout file under res ⇒ layout named drawer_list_item.xml. This is a relative layout which places the icon, title and counter relative to one another.






As each list item contains three elements icon, title and a counter, I would like create a model to represent each list row.
9. I prefer to create a new package to keep all the model classes. So create a new package named info.androidhive.slidingmenu.model
10. Under model package create a new class named NavDrawerItem.java and paste the following code. Here isCounterVisible defines the visibility of the counter value. If you don’t want to show a counter for a particular list item you can set this to false.






11. Also create another package to keep all the adapter classes. Create a package named info.androidhive.slidingmenu.adapter.
12. Now we have all the files required for custom list adapter. So create a class named NavDrawerListAdapter.java under adapter package.







Until now we are done creating all the required layouts, model and adapter class for navigation drawer. It’s time to move on to our MainActivity.java and start implementing the navigation drawer.
Following are the major steps we need take care of in the main activity.
> Creating a NavDrawerListAdapter instance and adding list items.
> Assigning the adapter to Navigation Drawer ListView
> Creating click event listener for list items
> Creating and displaying fragment activities on selecting list item.
13. So open your MainActivity.java and add the following code. In the following code, we declared required variables, loaded the list items titles and icons from strings.xml, created an adapter and added each list item. Finally we added a navigation drawer listener.
invalidateOptionsMenu() is called in onDrawerOpened() and onDrawerClosed() to hide and show the action bar icons on navigation drawer opened and closed.







Now if you run your project you can see the navigation drawer with a listview. You can open the navigation drawer either clicking on action bar app icon or swiping the screen left edge to right. But you can notice that the click event for list item not working as it is not enabled yet.

Creating Fragment Views for individual List Item

You can see we have Home, Find People, Photos, Communities, Pages and What’s Hot in the list view. Here each list item represents a view where each view needs a Fragment class and a xml layout file.
14. So create a class file named HomeFragment.java and a layout file named fragment_home.xml with following content. For demo purpose I have created very simple layout for this view. You can customize this view depending on your app design.











Also you need to create remaining fragment classes and layout files for other list items.

Handling Navigation Drawer List Item Click Event

When user selects a list item from navigation drawer, we need to display respected view in the main view. This can be done by adding a list item click listener and loading respected fragment view in the call back event.
15. Open the MainActivity.java and add the following code. Here we added a click listener and loaded the related fragment view.







Now run the project and test the listview click event. You can see respected fragment is loading on selecting the list item. Following is the screenshot of my slider menu.
android navigation drawer sliding menu

Final Code

MainActivity.java












Android Styles and Themes

If you already know about Cascading Style Sheet (CSS) in web design then to understand Android Style also works very similar way. There are number of attributes associated with each Android widget which you can set to change your application look and feel. A style can specify properties such as height, padding, font color, font size, background color, and much more.
You can specify these attributes in Layout file as follows:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
   android:layout_width="fill_parent"
   android:layout_height="fill_parent"
   android:orientation="vertical" >

   <TextView
   android:id="@+id/text_id"
   android:layout_width="wrap_content"
   android:layout_height="wrap_content"
   android:capitalize="characters"
   android:textColor="#00FF00"
   android:typeface="monospace"
   android:text="@string/hello_world" />

</LinearLayout>
But this way we need to define style attributes for every attribute separately which is not good for source code maintenance point of view. So we work with styles by defining them in separate file as explained below.


Defining Styles

A style is defined in an XML resource that is separate from the XML that specifies the layout. This XML file resides under res/values/ directory of your project and will have <resources> as the root node which is mandatory for the style file. The name of the XML file is arbitrary, but it must use the .xml extension.
You can define multiple styles per file using <style> tag but each style will have its name that uniquely identifies the style. Android style attributes are set using <item> tag as shown below:
<?xml version="1.0" encoding="utf-8"?>
<resources>
   <style name="CustomFontStyle">
      <item name="android:layout_width">fill_parent</item>
      <item name="android:layout_height">wrap_content</item>
      <item name="android:capitalize">characters</item>
      <item name="android:typeface">monospace</item>
      <item name="android:textSize">12pt</item>
      <item name="android:textColor">#00FF00</item>/> 
   </style>
</resources>
The value for the <item> can be a keyword string, a hex color, a reference to another resource type, or other value depending on the style property.

Using Styles

Once your style is defined, you can use it in your XML Layout file using style attribute as follows:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
   android:layout_width="fill_parent"
   android:layout_height="fill_parent"
   android:orientation="vertical" >

   <TextView
   android:id="@+id/text_id"
   style="@style/CustomFontStyle"
   android:text="@string/hello_world" />

</LinearLayout>
To understand the concept related to Android Style, you can check Style Demo Example.

Style Inheritance

Android supports style Inheritance in very much similar way as cascading style sheet in web design. You can use this to inherit properties from an existing style and then define only the properties that you want to change or add.
Its simple, to create a new style LargeFont that inherits the CustomFontStyle style defined above, but make the font size big, you can author the new style like this:
<?xml version="1.0" encoding="utf-8"?>
<resources>
   <style name="CustomFontStyle.LargeFont">
      <item name="android:textSize">20ps</item>
   </style>
</resources>
You can reference this new style as @style/CustomFontStyle.LargeFont in your XML Layout file. You can continue inheriting like this as many times as you'd like, by chaining names with periods. For example, you can extend FontStyle.LargeFont to be Red, with:
<?xml version="1.0" encoding="utf-8"?>
<resources>
   <style name="CustomFontStyle.LargeFont.Red">
      <item name="android:textColor">#FF0000</item>/> 
   </style>
</resources>
This technique for inheritance by chaining together names only works for styles defined by your own resources. You can't inherit Android built-in styles this way. To reference an Android built-in style, such as TextAppearance, you must use the parent attribute as shown below:
<?xml version="1.0" encoding="utf-8"?>
<resources>
   <style name="CustomFontStyle" parent="@android:style/TextAppearance">
      <item name="android:layout_width">fill_parent</item>
      <item name="android:layout_height">wrap_content</item>
      <item name="android:capitalize">characters</item>
      <item name="android:typeface">monospace</item>
      <item name="android:textSize">12pt</item>
      <item name="android:textColor">#00FF00</item>/> 
   </style>
</resources>

Android Themes

Hope you understood the concept of Style, so now let's try to understand what is a Theme. A theme is nothing but an Android style applied to an entire Activity or application, rather than an individual View.
Thus, when a style is applied as a theme, every View in the Activity or application will apply each style property that it supports. For example, you can apply the same CustomFontStyle style as a theme for an Activity and then all text inside that Activity will have green monospace font.
To set a theme for all the activities of your application, open the AndroidManifest.xml file and edit the <application> tag to include the android:theme attribute with the style name. For example:
<application android:theme="@style/CustomFontStyle">
But if you want a theme applied to just one Activity in your application, then add the android:theme attribute to the <activity> tag only. For example:
<activity android:theme="@style/CustomFontStyle">
There are number of default themes defined by Android which you can use directly or inherit them using parent attribute as follows:
<style name="CustomTheme" parent="android:Theme.Light">
    ...
</style>
To understand the concept related to Android Theme, you can check Theme Demo Example.