How To: Make the Android DrawerLayout Widget More Responsive

The DrawerLayout is a great Android widget for creating a sliding menu drawer navigation, but it might result in a few problems that can be easily avoided with just a small amount of coding. In this post, We’ll look at a couple ways to improve the user experience when interacting with the sliding menu drawer widget.

Saml plugin

The first problem some developers might notice when using DrawerLayout is a stuttering of the ‘close animation’ when an event is triggered by selecting a menu item and then closing the drawer widget. Some devices don’t have sufficient processing power to do both of these activities at the same time. However, there is a simple workaround to this problem.

By overriding the onDrawerClosed method of the ActionBarDrawerToggle class, we can wait until the drawer is closed before firing out the event. This will give the device a chance to run all the animations before diverting its attention to creating the next view that is being requested by the menu item selected.

Here is some sample code for ActionBarDrawerToggle with the onDrawerClosed method:

ActionBarDrawerToggle mDrawerToggle = new ActionBarDrawerToggle(getActivity(), /* host Activity */
                mDrawerLayout,                    /* DrawerLayout object */
                R.drawable.ic_drawer,             /* nav drawer image to replace 'Up' caret */
                R.string.navigation_drawer_open,  /* "open drawer" description for accessibility */
                R.string.navigation_drawer_close  /* "close drawer" description for accessibility */) {
           
            @Override
            public void onDrawerClosed(View drawerView) {
                super.onDrawerClosed(drawerView);
       
                if (!isAdded()) {
                    return;
                }

                //the item selected from the navigation menu is used to create a new fragment to display
                if (null != mSelectedFragmentId) {
                // MyFragmentUtilClass is a static utility class used to create
                // fragments from an id that is return from the menu adapter OnItemClickListener

                  Fragment frag = MyFragmentUtilClass.getFragment(mSelectedFragmentId);
                  getFragmentManager().beginTransaction().replace(android.R.id.content,frag).commit();
                }
                mSelectedFragmentId = null;
            }
}

 mDrawerLayout.setDrawerListener(mDrawerToggle);

The next thing to fine tune is when to hide the actionbar items based on the drawer being open or closed. One option is to use the same ActionBarDrawerToggle class and override both the onDrawerClosed method and the onDrawerOpened method. But this leads to the menu being closed all the way, and still showing the actionbar items associated with the DrawerLayout fragment.

A more responsive way to hide the actionbar items is by Overriding the onDrawerSlide method. By listening to the position of the sliding drawer, we can hide the actionbar items as the sliding menu begins to open and replace them with menu-specific items. We’ll add a boolean to this that keeps track of the state of the drawer, and use it to determine which actionbar item to show when we call invalidate options menu.

Here is the code that demonstrates this by tracking the drawer’s position:

boolean isOpening;

….. some code like onCreate ect.

private void setupDrawer(){
ActionBarDrawerToggle mDrawerToggle = new ActionBarDrawerToggle(getActivity(), /* host Activity */
                mDrawerLayout,                    /* DrawerLayout object */
                R.drawable.ic_drawer,             /* nav drawer image to replace 'Up' caret */
                R.string.navigation_drawer_open,  /* "open drawer" description for accessibility */
                R.string.navigation_drawer_close  /* "close drawer" description for accessibility */) {
           
            @Override
            public void onDrawerClosed(View drawerView) {
                super.onDrawerClosed(drawerView);
       
                if (!isAdded()) {
                    return;
                }

                //the item selected from the navigation menu is used to create a new fragment to display
                if (null != mSelectedFragmentId) {
                // MyFragmentUtilClass is a static utility class used to create
                // fragments from an id that is return from the menu adapter OnItemClickListener

                  Fragment frag = MyFragmentUtilClass.getFragment(mSelectedFragmentId);
                  getFragmentManager().beginTransaction().replace(android.R.id.content,frag).commit();
                }
                mSelectedFragmentId = null;
            }

            @Override
            public void onDrawerSlide(View drawerView, float slideOffset) {
              if (slideOffset < .7f && !isOpening) {
                isOpening = true;
                getActivity().invalidateOptionsMenu(); // calls onPrepareOptionsMenu()
              }

              if (slideOffset == 0) {
                isOpening = false;
                getActivity().invalidateOptionsMenu(); // calls onPrepareOptionsMenu()
              }

              super.onDrawerSlide(drawerView, slideOffset);
           }
    };

}

 mDrawerLayout.setDrawerListener(mDrawerToggle);
}

The last thing to check is if the drawer is open or closed when we draw our actionbar item in the onPrepareOptionMenu method. If the menu is open or opening, we will hide them; if the menu is closed, we will display them by setting the visibility of the menu group.

@Override
    public boolean onPrepareOptionsMenu(Menu menu) {
        if ( isOpening)) {
            menu.setGroupVisible(R.id.menu_group_privacy, false);
        } else {
            menu.setGroupVisible(R.id.menu_group_privacy, true);
        }
        return true;
    }

By following the above tips, you should be able to make your DrawerLayout widget more responsive, and in turn, create a more seamless Android experience for your users.

Speaking of Android apps, have you taken a look at the new features we added to the New Relic Android app? To learn more, read: “New Relic Android App Now Offers SAML and Plugin Support.”

larry@newrelic.com'

Larry Wegener has been developing Android applications since 2010. After receiving his degree from DePaul University, he began developing mobile apps professionally first for the iOS platform. He quickly moved to the Android platform because of client demand and has been developing Android applications ever since. He has developed apps for Postcard on the Run, Food Network, Google and Intel. He’s currently developing Android applications for New Relic at their Portland Oregon office after a lifetime of living in the Upper Midwest. He can be contacted at larry@newrelic.com View posts by .

Interested in writing for New Relic Blog? Send us a pitch!