Intro
This post is the first part of three posts series. In this post we will create a navigation drawer in an android project using Views instead of Fragments. In the second part we will see how to add a toggle button on the navigation drawer and add listeners for that button, and in the third part we will see a simple way to add a drop-down items on a navigation drawer without using ExpandableListView.
The navigation drawer is a UI panel that shows your app’s main navigation menu. The drawer appears when the user touches the drawer icon in the app bar or when the user swipes a finger from the left edge of the screen.
The Exercise
First we are going to create a new project in Android Studio. I will name the project Navigation Drawer Exercise, but you can use whatever name you find suiting. In this project I will be using ButterKife Library, if you have not used it before, you can find instructions here. Also we will have to add the android design library in order to create the navigation drawer. In your app/build.gradle file add the dependency “implementation ‘com.android.support:design:28.0.0′”.
We will create an empty activity named HomeActivity. When created the layout of this activity will look like this:
To add a navigation drawer, we must replace the root layout Constraint Layout with Drawer Layout. The xml code will look like this. We are adding a Frame Layout that we will be using to add different views on the home screen. The color attributes are optional and they depend on your desire.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
<?xml version="1.0" encoding="utf-8"?> <android.support.v4.widget.DrawerLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:id="@+id/drawer" android:layout_width="match_parent" android:layout_height="match_parent" tools:context=".HomeActivity"> <FrameLayout android:id="@+id/container" android:layout_width="match_parent" android:layout_height="match_parent" /> <android.support.design.widget.NavigationView android:id="@+id/mDrawerLayout" android:layout_width="wrap_content" android:layout_height="match_parent" android:layout_gravity="start" android:background="@drawable/nav_bg" app:menu="@menu/drawer_menu"> </android.support.design.widget.NavigationView> </android.support.v4.widget.DrawerLayout> |
Next you have to create a new Android Resource Directory of type menu. To do this you need to do a right click on the res folder in project view on android studio and select new – Android Resource File.
Then change the resource type of the file to menu and name it accordingly:
Inside the menu xml file create the menu items that you will need. We will create three menu items: Home, Profile and Logout. A menu item should have three parts: id, title and icon.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
<?xml version="1.0" encoding="utf-8"?> <menu xmlns:android="http://schemas.android.com/apk/res/android"> <item android:id="@+id/home" android:icon="@drawable/ic_home_black_24dp" android:title="Home" /> <item android:id="@+id/profile" android:icon="@drawable/ic_account_box_black_24dp" android:title="Profile" > <item android:id="@+id/logout" android:icon="@drawable/ic_cancel_black_24dp" android:title="Logout"> </menu> |
To create icons for the menu items you need to right click on the drawable folder in android studio project view, then click New – Vector Asset.
After that click on the Clip Art icon and select your desired icon, click OK, then next and finish.
Next we need to create a custom toolbar and include it in the home activity’s layout and a custom header for the navigation drawer. Also you will need to change the style of home activity, to select a different no-toolbar theme, so that your custom theme will be shown. First let’s create the toolbar, right click on the layout folder and select New- Create new layout resource file.
In the toolbar we will create a TextView that will hold the toolbar title later on. The xml code for the toolbar will look like this:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
<?xml version="1.0" encoding="utf-8"?> <android.support.v7.widget.Toolbar xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/toolbar" android:layout_width="match_parent" android:layout_height="?attr/actionBarSize" android:layout_gravity="top" android:textAlignment="center"> <TextView android:id="@+id/toolbarTitle" android:layout_width="match_parent" android:layout_height="wrap_content" android:textSize="20sp" android:gravity="center" android:clickable="true" android:focusable="true" android:layout_marginEnd="60dp"> |
After that we need to change the style of the activity, so we open the AndroidManifest file and we change android: theme to android:theme=”@style/Theme.AppCompat.Light.NoActionBar”
After that in the activity_home.xml we will create an AppBar layout and a toolbar and include the toolbar layout we created before. The xml code for the home activity will now look like this:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 |
<?xml version="1.0" encoding="utf-8"?> <android.support.v4.widget.DrawerLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:id="@+id/drawer" android:layout_width="match_parent" android:layout_height="match_parent" tools:context=".HomeActivity"> <android.support.design.widget.AppBarLayout android:id="@+id/appBar" android:layout_width="match_parent" android:layout_height="wrap_content"> <android.support.v7.widget.Toolbar android:id="@+id/toolbarHome" android:layout_width="match_parent" android:layout_height="wrap_content" android:textAlignment="center" app:contentInsetEnd="0dp" app:contentInsetStart="0dp" android:background="@color/colorAccent"> <include layout="@layout/toolbar"/> </android.support.v7.widget.Toolbar> </android.support.design.widget.AppBarLayout> <FrameLayout android:id="@+id/container" android:layout_width="match_parent" android:layout_height="match_parent" android:layout_below="@id/appBar" /> <android.support.design.widget.NavigationView android:id="@+id/mDrawerLayout" android:layout_width="wrap_content" android:layout_height="match_parent" android:layout_gravity="start" android:background="@drawable/nav_bg" app:menu="@menu/drawer_menu"> </android.support.design.widget.NavigationView> </android.support.v4.widget.DrawerLayout> |
Now let’s create the header for the navigation drawer. We follow the same instructions for creating the toolbar. Right click on the layout folder and select New- Create new layout resource file. I will name the xml file header. In the header we will add just a TextView as a title and we will change the background color, but you can add whatever you need, profile picture, other elements, etc. The code for this layout file will look like this:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
<?xml version="1.0" encoding="utf-8"?> <android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="150dp" android:orientation="horizontal" android:padding="20dp" android:background="@color/colorPrimaryDark"> <TextView android:id="@+id/userNameEditText" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginStart="18sp" android:layout_marginTop="24dp" android:text="Navigation Drawer" android:textColor="@android:color/white" android:textSize="16sp" android:textStyle="bold" app:layout_constraintTop_toTopOf="parent" app:layout_constraintStart_toStartOf="parent" /> </android.support.constraint.ConstraintLayout> |
We will add the header.xml in the NavigationView element in activity_home.xml, like this:
1 2 3 4 5 6 7 8 9 10 11 |
<android.support.design.widget.NavigationView android:id="@+id/mDrawerLayout" android:layout_width="wrap_content" android:layout_height="match_parent" android:layout_gravity="start" android:fitsSystemWindows="false" android:layout_marginStart="30dp" <strong>app:headerLayout="@layout/header"</strong> app:menu="@menu/drawermenu" app:itemTextColor="@color/colorPrimaryDark"> </android.support.design.widget.NavigationView> |
Now that our layout is done we move in the HomeActivity.java. We will be using ButterKnife to bind the layout files, and first we declare our variables and bind our layout elements :
1 2 3 4 5 6 7 8 9 10 |
private DrawerLayout mDrawerLayout; private ActionBarDrawerToggle mToggle; @BindView(R.id.mDrawerLayout) NavigationView navigationView; @BindView(R.id.container) FrameLayout container; @BindView(R.id.toolbar) Toolbar myToolbar; @BindView(R.id.toolbarTitle) TextView toolbarTitle; |
Then we will create a method that we will call setupUi() where we will do exactly what the name says, set up the UI. This method we will call in the onCreate().
1 2 3 4 5 6 7 8 9 10 |
private void setupUi() { mDrawerLayout = findViewById(R.id.drawer); mToggle = new ActionBarDrawerToggle(this, mDrawerLayout, myToolbar, R.string.open, R.string.close); mDrawerLayout.addDrawerListener(mToggle); mDrawerLayout.setClickable(true); setSupportActionBar(myToolbar); mToggle.setDrawerIndicatorEnabled(true); mToggle.syncState(); } |
You will notice that R.string.open and R.string.open are turning red. You will need to create this strings. In the res/values folder in the strings.xml file we will add two more strings
1 2 |
<string name="open">Open</string> <string name="close">Close</string> |
If you run the app now, you will notice that you can open the navigation drawer by swiping, but the burger button on the toolbar does nothing. To give this button functionality we will need to override another method in home activity:
1 2 3 4 5 6 7 8 |
@Override public boolean onOptionsItemSelected(MenuItem item) { if (mToggle.onOptionsItemSelected(item)) { return true; } else { return super.onOptionsItemSelected(item); } } |
Now run the app again and the burger button does his job of opening the drawer menu.
Now you will see how to use View instead of Fragment. You can read more about that here. We will create another Java class named Profile. Right click on the package name and select New – Java Class.
After this we will crate a new layout resource file named view_profile.xml. You already know this, right click on the layout folder and select New- Create new layout resource file. In this layout file we will just add one TextView that will display the text “This is profile page”. It will look like this:
1 2 3 4 5 6 7 8 9 10 11 12 13 |
<?xml version="1.0" encoding="utf-8"?> <android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent"> <TextView android:layout_width="match_parent" android:layout_height="match_parent" android:text="This is profile view" android:textSize="60dp" android:gravity="center_horizontal"/> </android.support.constraint.ConstraintLayout> |
Now in the Profile class we will add code to bind this view in the class. First we will extend this class with the ConstraintLayout class, than we will create a constructor with context as parameter, and call super in the constructor. We will create a method named init() where we will inflate the view_profile layout. It will look like this:
1 2 3 4 5 6 7 8 9 10 11 |
public class Profile extends ConstraintLayout { public Profile(Context context) { super(context); init(); } private void init() { inflate(getContext(), R.layout.view_profile, this); } } |
Now we will go back in the HomeActivity class and we will set the code to get a functional navigation drawer. We will create two new methods setupNavigationView() and switchScreen(int id). First in the switchScreen(int id) method we will create a switch where we will go through all of the menu items in the navigation drawer and add functionality they will perform when clicked. In our case when we click on “Home” we want to start the home activity, when clicked on “Profile” we want to add the profile view, and when clicked on “Logout we want to leave the app. This method will look like this:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
private void switchScreen(int id) { switch (id) { case R.id.home: container.removeAllViews(); startActivity(new Intent(this, HomeActivity.class)); toolbarTitle.setText("Home"); mDrawerLayout.closeDrawers(); break; case R.id.profile: container.removeAllViews(); container.addView(new Profile(this)); mDrawerLayout.closeDrawers(); break; case R.id.logout: finish(); break; } |
In the other method, setupNavigationView() we will add a listener so that we will know when a menu item is selected and we will call the switchScreen(id) method on click. We will call this method in the setupUi method.
1 2 3 4 5 6 7 8 9 10 |
private void setupNavigationView() { navigationView.setNavigationItemSelectedListener(new NavigationView.OnNavigationItemSelectedListener() { @Override public boolean onNavigationItemSelected(@NonNull MenuItem item) { switchScreen(item.getItemId()); return true; } }); } |
1 2 3 4 5 6 7 8 9 10 11 |
private void setupUi() { mDrawerLayout = findViewById(R.id.drawer); mToggle = new ActionBarDrawerToggle(this, mDrawerLayout, myToolbar, R.string.open, R.string.close); mDrawerLayout.addDrawerListener(mToggle); mDrawerLayout.setClickable(true); setSupportActionBar(myToolbar); setupNavigationView(); mToggle.setDrawerIndicatorEnabled(true); mToggle.syncState(); } |
We can also make home as a view instead of activity, but it was good to see how to start an activity from the navigation drawer. This is our final result:
You can get the whole project here : https://github.com/AleksandarGulevski/NavigationDrawerExercise
See you in part two. Happy coding!