Skip to content
This repository was archived by the owner on Mar 3, 2023. It is now read-only.

Android_Menu and Navigation

Miroslav Smukov edited this page Jun 16, 2016 · 5 revisions

Menu and Navigation

I'm getting to a point where I want to continue extending my application by adding new screens to it (e.g. - My Profile and Settings). However, before I start with that, I need to establish a way to navigate through those screens via the navigation drawer I already have implemented. So, this page will describe how I implemented this.

A frame for my screens

Before I start implementing the navigation, I need a place where my new screens will appear when I click on the navigation drawer options. When I generated the project with the Navigation Drawer Activity template, it generated an xml file for me called content_navigation.xml. This view represents the main part of the screen layout for the NavigationActivity. It is highlighted in red in the image below, but keep in mind that it doesn't include the Floating Action Button, that is actually a part of another layout, that includes the content_navigation.xml layout.

Content Navigation Layout

Initially, the content_navigation.xml contains a TextView with a Hellow World! text. I'm going to delete this view and instead add the FrameLayout:

Source Code

<FrameLayout
    android:id="@+id/content_frame"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    ></FrameLayout>

This FrameLayout is where my new screen layouts (e.g. - My Profile, Settings, etc) will appear (load into) when a user clicks on the Navigation Drawer option.

What is FrameLayout?

As per Android documentation:

FrameLayout is designed to block out an area on the screen to display a single item. Generally, FrameLayout should be used to hold a single child view.

Child views are drawn in a stack, with the most recently added child on top. The size of the FrameLayout is the size of its largest child (plus padding), visible or not (if the FrameLayout's parent permits).

Create 2 new layouts and fragments (My Profile, Settings)

We are now going to create a layout and a controller for the two new "screens" that are going to appear when the user clicks on the Navigation Drawer options. I'll walk you to creation of one of those screens, as the second one is completely the same, just with different names.

So, firstly, I'm going to create a layout part called profile_layout.xml inside the res/layout folder:

Source Code

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical" android:layout_width="match_parent"
    android:layout_height="match_parent">

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="My Profile Page" />

</LinearLayout>

Next, I'll create a controller for this layout. Usually this would be a new Activity, but in this case it will be a Fragment, since we are loading this into the FrameLayout instead of inflating the whole new Activity.

Source Code

public class ProfileFragment extends Fragment{

    View myView;

    @Nullable
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        myView = inflater.inflate(R.layout.profile_layout, container, false);
        return myView;
    }
}

What are fragments?

As per Android documentation:

A Fragment represents a behavior or a portion of user interface in an Activity. You can combine multiple fragments in a single activity to build a multi-pane UI and reuse a fragment in multiple activities. You can think of a fragment as a modular section of an activity, which has its own lifecycle, receives its own input events, and which you can add or remove while the activity is running (sort of like a "sub activity" that you can reuse in different activities).

Interaction with fragments is done through FragmentManager, which can be obtained via Activity.getFragmentManager() and Fragment.getFragmentManager().

Clear up the Menu options

Now I need to remove the unnecessary menu options that were generated with the project, and define the appropriate IDs so I can handle the navigation correctly. The menu options are defined inside the res/menu/activity_navigation_drawer.xml file. I'm going to remove all of the options and change the code to the one below:

Source Code

<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">

    <group
        android:id="@+id/menu_top"
        android:checkableBehavior="single">
        <item
            android:checked="true"
            android:id="@+id/nav_my_profile"
            android:icon="@drawable/ic_menu_camera"
            android:title="My Profile" />
    </group>

    <group
        android:id="@+id/menu_bottom"
        android:checkableBehavior="single">
        <item
            android:id="@+id/nav_settings"
            android:icon="@drawable/ic_menu_manage"
            android:title="Settings" />
        <item
            android:id="@+id/nav_send_feedback"
            android:icon="@drawable/ic_menu_send"
            android:title="Send Feedback" />
    </group>

</menu>

Over time I'll add more options, but for now the ones I have will be enough.

Also, a useful thing to know is that by default, these group elements don't have an id assigned to them. But if you want to have a separator in the UI between different groups (sections) of your menu options, you need to add those id fields and make them unique between all of the group elements. You'll see the separator I'm talking about below in the screenshot between the first, and the last two buttons.

Show the navigation implementation in NavigationActivity

Finally, we need to implement the navigation logic.

We'll do this in NavigationActivity by firstly importing the android.app.FragmentManager package. Next, we'll define a class wide variable FragmentManager fragmentManager at the start of the class definition, so we can access it from anywhere within our activity.

There is already a generated method onNavigationItemSelected that is called whenever a user clicks on the Navigation Item (Menu Item), but the navigation logic wasn't implemented, so we are going to add it now, and remove the extra if statements that we aren't going to use:

    @Override
    public boolean onNavigationItemSelected(MenuItem item) {
        // Handle navigation view item clicks here.
        int id = item.getItemId();

        if (id == R.id.nav_my_profile) {
            fragmentManager.beginTransaction()
                    .replace(R.id.content_frame, new ProfileFragment())
                    .commit();
        } else if (id == R.id.nav_settings) {
            fragmentManager.beginTransaction()
                    .replace(R.id.content_frame, new SettingsFragment())
                    .commit();
        } else if (id == R.id.nav_send_feedback) {

        }

        DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
        drawer.closeDrawer(GravityCompat.START);
        return true;
    }

So, whenever a user clicks on the My Profile menu option, the MenuItem will have an id of value nav_my_profile and the corresponding if statement logic will be triggered. Same goes for Settings MenuItem. The logic within those if statements replaces the content of the FrameLayout we defined in the content_navigation.xml file with one of the fragments, using the fragmentManager object.

Finally, we need to make the "My Profile" view (fragment) as the default one when the user opens the application, before he even selects any of the options in the Navigation Drawer. We are going to do that by adding the code below at the end of the onCreate method in NavigationActivity.

//instantiate the fragmentManager and set the default view to profile
fragmentManager = getFragmentManager();
fragmentManager.beginTransaction()
    .replace(R.id.content_frame ,new ProfileFragment())
    .commit();

You can see the full source code of the NavigationActivity class here

End Result

In the image below you can see the end results. There are the 3 menu options we defined, and the separator between the first and second option, which are contained in different groups.

Navigation Drawer

Conclusion

Implementing this navigation was pretty straightforward was I found the correct documentation and knew what to change.

Resources

Clone this wiki locally