官术网_书友最值得收藏!

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:

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

See also

  • Creating and using fragments
主站蜘蛛池模板: 怀来县| 德江县| 玉山县| 诸暨市| 江城| 镇远县| 阜城县| 大化| 应城市| 武定县| 北京市| 饶河县| 景德镇市| 阳江市| 扎兰屯市| 海丰县| 辽阳市| 阿拉善左旗| 宾阳县| 盐津县| 阳西县| 枣庄市| 双江| 南涧| 黄大仙区| 敖汉旗| 北京市| 赤水市| 大悟县| 徐水县| 潼南县| 巫溪县| 铁岭市| 纳雍县| 通榆县| 万山特区| 大竹县| 左云县| 田阳县| 曲阳县| 常熟市|