Navigation Drawer--左侧滑导航

文章出处:http://blog.csdn.net/xyz_lmn/article/details/12523895

 Navigation Drawer是从屏幕的左侧滑出,显示应用导航的视图。官方是这样定义的:

[html]  view plain copy print ?
  1. The navigation drawer is a panel that displays the app’s main   
  2.     navigation options on the left edge of the screen. It is hidden   
  3.     most of the time, but is revealed when the user swipes a finger   
  4.     from the left edge of the screen or, while at the top level of the   
  5.     app, the user touches the app icon in the action bar.  


如下图指示:



       Navigation Drawer不同于SlidingDrawer,它不存在可以拖动的handle;它也不同于SlidingMenu,Navigation Drawer滑出时主屏幕视图不一定。Navigation Drawer是覆盖在主视图上的。

       Navigation Drawer是Android团队在2013 google IO大会期间更新的Support库(V13)中新加入的重要的功能。实现现Navigation Drawer需要使用最新支持库(V13)的DrawerLayout。Navigation Drawer的设计指南请参考 

Navigation Drawer design guide

http://my.eoe.cn/appadventure/archive/3826.html

Create a Drawer Layout


        创建Navigation Drawer需要用DrawerLayout 作为界面根控件。在DrawerLayout里面第一个View为当前界面主内容;第二个和第三个View为Navigation Drawer内容。如果当前界面只需要一个Navigation Drawer,则第三个View可以省略。


      下面的例子中DrawerLayout里面包含两个View,第一个FrameLayout中是当前界面主要内容显示区域;第二个ListView为Navigation Drawer内容。

  1. <android.support.v4.widget.DrawerLayout  
  2.     xmlns:android="http://schemas.android.com/apk/res/android"  
  3.     android:id="@+id/drawer_layout"  
  4.     android:layout_width="match_parent"  
  5.     android:layout_height="match_parent">  
  6.     <!-- The main content view -->  
  7.     <FrameLayout  
  8.         android:id="@+id/content_frame"  
  9.         android:layout_width="match_parent"  
  10.         android:layout_height="match_parent" />  
  11.     <!-- The navigation drawer -->  
  12.     <ListView android:id="@+id/left_drawer"  
  13.         android:layout_width="240dp"  
  14.         android:layout_height="match_parent"  
  15.         android:layout_gravity="start"  
  16.         android:choiceMode="singleChoice"  
  17.         android:divider="@android:color/transparent"  
  18.         android:dividerHeight="0dp"  
  19.         android:background="#111"/>  
  20. </android.support.v4.widget.DrawerLayout>  

上面的代码中有如下几点需要注意:


    • 1、显示界面主要内容的View (上面的 FrameLayout ) 必须为DrawerLayout的第一个子View, 原因在于 XML 布局文件中的View顺序为Android系统中的 z-ordering顺序,而Navigation Drawer必须出现在内容之上。

    • 2、显示界面内容的View宽度和高度设置为和父View一样,原因在于当Navigation Drawer不可见的时候,界面内容代表整个界面UI。

    • 3、Navigation Drawer (上面的 ListView必须使用android:layout_gravity属性设置水平的 gravity值 .如果要支持 right-to-left (RTL,从右向左阅读)语言 用 "start" 代替 "left" (当在 RTL语言运行时候,菜单出现在右侧)。

    • 4、抽屉菜单的宽度为 dp 单位而高度和父View一样。抽屉菜单的宽度应该不超过320dp,这样用户可以在菜单打开的时候看到部分内容界面。

Initialize the Drawer List


       在您的Activity中需要先初始化Navigation Drawer内容,根据您的应用需要Navigation Drawer的内容可能不是ListView,可以使用其他View。


      在上面的示例中,我们需要给Navigation Drawer的ListView设置一个Adapter来提供数据。如下所示:


  1. public class MainActivity extends Activity {  
  2.     private String[] mPlanetTitles;  
  3.     private DrawerLayout mDrawerLayout;  
  4.     private ListView mDrawerList;  
  5.     ...  
  6.   
  7.     @Override  
  8.     public void onCreate(Bundle savedInstanceState) {  
  9.         super.onCreate(savedInstanceState);  
  10.         setContentView(R.layout.activity_main);  
  11.   
  12.         mPlanetTitles = getResources().getStringArray(R.array.planets_array);  
  13.         mDrawerLayout = (DrawerLayout) findViewById(R.id.drawer_layout);  
  14.         mDrawerList = (ListView) findViewById(R.id.left_drawer);  
  15.   
  16.         // Set the adapter for the list view  
  17.         mDrawerList.setAdapter(new ArrayAdapter<String>(this,  
  18.                 R.layout.drawer_list_item, mPlanetTitles));  
  19.         // Set the list's click listener  
  20.         mDrawerList.setOnItemClickListener(new DrawerItemClickListener());  
  21.   
  22.         ...  
  23.     }  
  24. }  

      上面的代码调用了 setOnItemClickListener() 函数来接受Navigation Drawer点击事件。下面会介绍如何通过点击Navigation Drawer显示主界面内容。

Handle Navigation Click Events


       当用户选择Navigation Drawer List中的条目时,系统会调用  OnItemClickListener的 onItemClick()函数。


       根据您的应用需要,onItemClick函数的实现方式可能不同。下面的示例中,选择Navigation Drawer条目会在程序主界面中插入不同的 Fragment 。

  1. private class DrawerItemClickListener implements ListView.OnItemClickListener {  
  2.     @Override  
  3.     public void onItemClick(AdapterView parent, View view, int position, long id) {  
  4.         selectItem(position);  
  5.     }  
  6. }  
  7.   
  8. /** Swaps fragments in the main content view */  
  9. private void selectItem(int position) {  
  10.     // Create a new fragment and specify the planet to show based on position  
  11.     Fragment fragment = new PlanetFragment();  
  12.     Bundle args = new Bundle();  
  13.     args.putInt(PlanetFragment.ARG_PLANET_NUMBER, position);  
  14.     fragment.setArguments(args);  
  15.   
  16.     // Insert the fragment by replacing any existing fragment  
  17.     FragmentManager fragmentManager = getFragmentManager();  
  18.     fragmentManager.beginTransaction()  
  19.                    .replace(R.id.content_frame, fragment)  
  20.                    .commit();  
  21.   
  22.     // Highlight the selected item, update the title, and close the drawer  
  23.     mDrawerList.setItemChecked(position, true);  
  24.     setTitle(mPlanetTitles[position]);  
  25.     mDrawerLayout.closeDrawer(mDrawerList);  
  26. }  
  27.   
  28. @Override  
  29. public void setTitle(CharSequence title) {  
  30.     mTitle = title;  
  31.     getActionBar().setTitle(mTitle);  
  32. }  

Listen for Open and Close Events


        如果需要监听菜单打开关闭事件,则需要调用 DrawerLayout类的 setDrawerListener() 函数,参数为 DrawerLayout.DrawerListener接口的实现。该接口提供了菜单打开关闭等事件的回调函数,例如 onDrawerOpened() 和onDrawerClosed().


    如果您的Activity使用了 action bar,则您可以使用Support库提供的 ActionBarDrawerToggle 类,该类实现了 DrawerLayout.DrawerListener接口,并且您还可以根据需要重写相关的函数。该类实现了菜单和Action bar相关的操作。


    根据在 Navigation Drawer 设计指南中的介绍,当菜单显示的时候您应该根据情况隐藏ActionBar上的功能菜单并且修改ActionBar的标题。下面的代码演示了如何重写 ActionBarDrawerToggle 类的相关函数来实现该功能。


  1. public class MainActivity extends Activity {  
  2.     private DrawerLayout mDrawerLayout;  
  3.     private ActionBarDrawerToggle mDrawerToggle;  
  4.     private CharSequence mDrawerTitle;  
  5.     private CharSequence mTitle;  
  6.     ...  
  7.   
  8.     @Override  
  9.     public void onCreate(Bundle savedInstanceState) {  
  10.         super.onCreate(savedInstanceState);  
  11.         setContentView(R.layout.activity_main);  
  12.         ...  
  13.   
  14.         mTitle = mDrawerTitle = getTitle();  
  15.         mDrawerLayout = (DrawerLayout) findViewById(R.id.drawer_layout);  
  16.         mDrawerToggle = new ActionBarDrawerToggle(this, mDrawerLayout,  
  17.                 R.drawable.ic_drawer, R.string.drawer_open, R.string.drawer_close) {  
  18.   
  19.             /** Called when a drawer has settled in a completely closed state. */  
  20.             public void onDrawerClosed(View view) {  
  21.                 getActionBar().setTitle(mTitle);  
  22.                 invalidateOptionsMenu(); // creates call to onPrepareOptionsMenu()  
  23.             }  
  24.   
  25.             /** Called when a drawer has settled in a completely open state. */  
  26.             public void onDrawerOpened(View drawerView) {  
  27.                 getActionBar().setTitle(mDrawerTitle);  
  28.                 invalidateOptionsMenu(); // creates call to onPrepareOptionsMenu()  
  29.             }  
  30.         };  
  31.   
  32.         // Set the drawer toggle as the DrawerListener  
  33.         mDrawerLayout.setDrawerListener(mDrawerToggle);  
  34.     }  
  35.   
  36.     /* Called whenever we call invalidateOptionsMenu() */  
  37.     @Override  
  38.     public boolean onPrepareOptionsMenu(Menu menu) {  
  39.         // If the nav drawer is open, hide action items related to the content view  
  40.         boolean drawerOpen = mDrawerLayout.isDrawerOpen(mDrawerList);  
  41.         menu.findItem(R.id.action_websearch).setVisible(!drawerOpen);  
  42.         return super.onPrepareOptionsMenu(menu);  
  43.     }  
  44. }  

Open and Close with the App Icon


    用户可以从屏幕边缘滑动来打开Navigation Drawer,如果您使用了 action bar,应该让用户通过点击应用图标也可以打开抽屉菜单。并且应用图标也应该使用一个特殊的图标来指示抽屉菜单。您可以使用 ActionBarDrawerToggle 类来实现这些功能。


    使用 ActionBarDrawerToggle ,先通过其构造函数来创建该对象,构造函数需要如下参数:

    • 1)显示Navigation Drawer的 Activity 对象
    • 2) DrawerLayout 对象
    • 3)一个用来指示Navigation Drawer的 drawable资源
    • 4)一个用来描述打开Navigation Drawer的文本 (用于支持可访问性)。
    • 5)一个用来描述关闭Navigation Drawer的文本(用于支持可访问性).

    无论你是否继承 ActionBarDrawerToggle 来实现Navigation Drawer监听器,您都需要在Activity的生命周期函数中调用ActionBarDrawerToggle 的一些函数。

如下所示:


  1. public class MainActivity extends Activity {  
  2.     private DrawerLayout mDrawerLayout;  
  3.     private ActionBarDrawerToggle mDrawerToggle;  
  4.     ...  
  5.   
  6.     public void onCreate(Bundle savedInstanceState) {  
  7.         ...  
  8.   
  9.         mDrawerLayout = (DrawerLayout) findViewById(R.id.drawer_layout);  
  10.         mDrawerToggle = new ActionBarDrawerToggle(  
  11.                 this,                  /* host Activity */  
  12.                 mDrawerLayout,         /* DrawerLayout object */  
  13.                 R.drawable.ic_drawer,  /* nav drawer icon to replace 'Up' caret */  
  14.                 R.string.drawer_open,  /* "open drawer" description */  
  15.                 R.string.drawer_close  /* "close drawer" description */  
  16.                 ) {  
  17.   
  18.             /** Called when a drawer has settled in a completely closed state. */  
  19.             public void onDrawerClosed(View view) {  
  20.                 getActionBar().setTitle(mTitle);  
  21.             }  
  22.   
  23.             /** Called when a drawer has settled in a completely open state. */  
  24.             public void onDrawerOpened(View drawerView) {  
  25.                 getActionBar().setTitle(mDrawerTitle);  
  26.             }  
  27.         };  
  28.   
  29.         // Set the drawer toggle as the DrawerListener  
  30.         mDrawerLayout.setDrawerListener(mDrawerToggle);  
  31.   
  32.         getActionBar().setDisplayHomeAsUpEnabled(true);  
  33.         getActionBar().setHomeButtonEnabled(true);  
  34.     }  
  35.   
  36.     @Override  
  37.     protected void onPostCreate(Bundle savedInstanceState) {  
  38.         super.onPostCreate(savedInstanceState);  
  39.         // Sync the toggle state after onRestoreInstanceState has occurred.  
  40.         mDrawerToggle.syncState();  
  41.     }  
  42.   
  43.     @Override  
  44.     public void onConfigurationChanged(Configuration newConfig) {  
  45.         super.onConfigurationChanged(newConfig);  
  46.         mDrawerToggle.onConfigurationChanged(newConfig);  
  47.     }  
  48.   
  49.     @Override  
  50.     public boolean onOptionsItemSelected(MenuItem item) {  
  51.         // Pass the event to ActionBarDrawerToggle, if it returns  
  52.         // true, then it has handled the app icon touch event  
  53.         if (mDrawerToggle.onOptionsItemSelected(item)) {  
  54.           return true;  
  55.         }  
  56.         // Handle your other action bar items...  
  57.   
  58.         return super.onOptionsItemSelected(item);  
  59.     }  
  60.   
  61.     ...  
  62. }  


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值