Adding a navigation drawer with fragments

The navigation drawer is a panel that transitions in from the left edge of the screen and displays the app's main navigation options.

How to do it...

We can add a navigation drawer to our app by setting the DrawerLayout type as the root layout container, with the contents of the drawer and the main content as subviews:

  1. The DrawerLayout type should be the root of our layout file, with two subviews: the first is the main content and the second is the drawer. Let's take a look at the following code snippet:
    <?xml version="1.0" encoding="utf-8"?>
    <android.support.v4.widget.DrawerLayout xmlns:android="http://schemas.android.com/apk/res/android"
      android:id="@+id/drawerLayout"
      android:layout_width="match_parent"
      android:layout_height="match_parent">
      <FrameLayout
        android:id="@+id/drawerContent"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />
      <ListView
        android:id="@+id/drawerList"
        android:layout_width="240dp"
        android:layout_height="match_parent"
        android:layout_gravity="start"
        android:choiceMode="singleChoice"
        android:divider="@android:color/transparent"
        android:dividerHeight="0dp"
        android:background="#111" />
    </android.support.v4.widget.DrawerLayout>
  2. Now we add an adapter to the list view that we are using and the event to handle item clicks:
    protected override void OnCreate(Bundle bundle) {
      base.OnCreate(bundle);
      SetContentView(Resource.Layout.Main);
    
      DrawerLayout drawerLayout = FindViewById<DrawerLayout>(Resource.Id.drawerLayout);
      FrameLayout drawerContent = FindViewById<FrameLayout>(Resource.Id.drawerContent);
      ListView drawerList = FindViewById<ListView>(Resource.Id.drawerList);
    
      drawerList.Adapter = new ArrayAdapter(
        this,
        Android.Resource.Layout.SimpleListItem1,
        new []{"First", "Second", "Third", "Fourth"});
    
      drawerList.ItemClick += (sender, e) => {
        ContentFragment content = new ContentFragment();
        Bundle args = new Bundle();
        args.PutInt(ContentFragment.ArgumentsKey, e.Position);
        content.Arguments = args;
    
        SupportFragmentManager
          .BeginTransaction()
          .Replace(Resource.Id.drawerContent, content)
          .Commit();
    
        drawerList.SetItemChecked(e.Position, true);
      };
    }
  3. In order to know when the user opens or closes the drawer, we need a drawer toggle:
    private class DrawerToggle : ActionBarDrawerToggle {
      public DrawerToggle(
        Activity activity, DrawerLayout drawerLayout)
      : base(
        activity, drawerLayout,
        Resource.String.drawer_open,
        Resource.String.drawer_close) {
        }
    
      public override void OnDrawerClosed(View drawerView) {
        base.OnDrawerClosed(drawerView);
        var handler = DrawerClosed;
        if (handler != null) {
          handler(this, EventArgs.Empty);
        }
      }
    
      public override void OnDrawerOpened(View drawerView) {
        base.OnDrawerOpened(drawerView);
        var handler = DrawerOpened;
        if (handler != null) {
          handler(this, EventArgs.Empty);
        }
      }
    
      public event EventHandler DrawerClosed;
      public event EventHandler DrawerOpened;
    }
  4. We then attach the drawer toggle to the drawer. When the drawer opens, we change the title of the screen to be the app title, and when it closes, we set the title to be the current page title:
    private DrawerToggle drawerToggle;
    
    protected override void OnCreate(Bundle bundle) {
      ...
      drawerList.ItemClick += (sender, e) => {
        ...
        drawerLayout.CloseDrawer(drawerList);
      };
    
      drawerToggle = new DrawerToggle(this, drawerLayout);
      drawerToggle.DrawerClosed += delegate {
        SupportActionBar.Title = "Xamarin Cookbook Item";
      };
      drawerToggle.DrawerOpened += delegate {
        SupportActionBar.Title = "Xamarin Cookbook";
      };
      drawerLayout.SetDrawerListener(drawerToggle);
    
      SupportActionBar.SetDisplayHomeAsUpEnabled(true);
      SupportActionBar.SetHomeButtonEnabled(true);
    }
  5. If we want to display the hamburger icon as the home button, we have to connect the activity event methods to the drawer toggle:
    protected override void OnPostCreate(
      Bundle savedInstanceState) {
        base.OnPostCreate(savedInstanceState);
        drawerToggle.SyncState();
      }
    
    public override void OnConfigurationChanged(
      Configuration newConfig) {
        base.OnConfigurationChanged(newConfig);
        drawerToggle.OnConfigurationChanged(newConfig);
      }
  6. And if we want the drawer to open when the user taps the home button, we have to connect the home button to the drawer toggle:
    public override bool OnOptionsItemSelected(IMenuItem item) {
      if (drawerToggle.OnOptionsItemSelected(item)) {
        return true;
      }
      return base.OnOptionsItemSelected(item);
    }
  7. Finally, we should hide the options menu items when the drawer is open. To do this, we can invalidate the options menu when the drawer is opened or closed:
    SupportInvalidateOptionsMenu();
  8. To check if the drawer is open, we can use the IsDrawerOpen() method:
    bool isOpen = drawerLayout.IsDrawerOpen(drawerList);

How it works...

The navigation drawer is a panel that displays the app's main navigation options on the left edge of the screen. It is hidden most of the time but is revealed when the user swipes a finger from the left edge of the screen or (while at the top level of the app) touches the app icon in the action bar.

The drawer layout subviews can be of any type; however, there is usually some container for the fragments and a list of options in the drawer. The order in which the views are added in is important. To keep the drawer above the main content, it must be added after the main content. It is also important for us to keep the drawer width a bit narrower than the screen to ensure that there is always a bit of main content for the user to see.

Tip

In order to support RTL languages, the drawer's horizontal gravity should be set to start instead of left.

Users can open and close the navigation drawer with a swipe gesture from or towards the left edge of the screen, but if we're using the action bar, we should also allow users to open and close it by touching the app icon. The app icon should also indicate the presence of the navigation drawer with a special icon. We can implement all this by using the ActionBarDrawerToggle.

We have to link the drawer toggle to the activity events in order for the drawer to respond to various events. We let the action bar know that we want to show an icon in the home button by enabling the home button and overriding the OnPostCreate() and OnConfigurationChanged() methods.

By overriding the OnOptionsItemSelected() method, we can intercept taps to the home button and pass it on to the drawer toggle, which will then show or hide the drawer.

Tip

The action bar should display the app title when the drawer opens and a title for the current context when it closes.

In order to remove conflicting information from the screen, we should remove the action bar items that do not apply to the drawer and any contextual action bar items when the drawer is opened. The following image is the Android navigation drawer:

How it works...

An app with an open navigation drawer over the main content.

See also

  • Creating and using fragments
..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset