Navigation Drawer的使用

创建一个Navigation Drawer

实例代码地址

navigation drawer是一个位于屏幕左侧用于显示应用主要导航选项的面板。一般情况下它是隐藏着的,当用户从屏幕左侧用手势划一下或者点击action bar上的app icon,它就会显示出来。

通过 Support Library中的 DrawerLayout来实现navigation drawer

创建一个Drawer Layout

为了添加一个navigation drawer ,用DrawerLayout布局作为你的Layout的根view来申明你的用户接口。在DrawerLyaout中一般添加两个view:第一个view用来显示主要内容(当drawer被隐藏时你的初始布局),第二个view包含了你的navigation drawer要显示的内容。
例如下面实例就是使用一个DrawerLayout包含两个子view视图:一个FrameLayout包含主要内容(运行时用fragment进行填充),另外一个是ListView对应于navigation drawer。

<android.support.v4.widget.DrawerLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/drawer_layout"
    android:layout_width="match_parent"
    android:layout_height="match_parent">
    <!-- The main content view -->
    <FrameLayout
        android:id="@+id/content_frame"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />
    <!-- The navigation drawer -->
    <ListView android:id="@+id/left_drawer"
        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>

上述布局演示了几个很重要的布局特点:

  • 主要内容视图(对于上述案例就是FrameLayout)必须是DrawerLayout的第一个子view。
  • 主要内容视图的width和height两个属性的值必须是match。
  • 抽屉视图(对于上述案例就是ListView)必须设置属性android:layout_gravity的属性值
  • 抽屉视图必须使用dp方式指定width的值和height的值是match。

初始化抽屉列表

在你的activity中,你要做的第一件事就是初始化导航抽屉中的列表项。你要怎么做完全取决于你的App的内容,但是一个导航抽屉往往包含了一个ListView,所以这个list应该通过一个Adapter来填充(比如 ArrayAdapter 或者 SimpleCursorAdapter)。

下面是通过一个字符串数组来填充抽屉列表的:

public class MainActivity extends Activity {
    private String[] mPlanetTitles;
    private DrawerLayout mDrawerLayout;
    private ListView mDrawerList;
    ...

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        mPlanetTitles = getResources().getStringArray(R.array.planets_array);
        mDrawerLayout = (DrawerLayout) findViewById(R.id.drawer_layout);
        mDrawerList = (ListView) findViewById(R.id.left_drawer);

        // Set the adapter for the list view
        mDrawerList.setAdapter(new ArrayAdapter<String>(this,
                R.layout.drawer_list_item, mPlanetTitles));
        // Set the list's click listener
        mDrawerList.setOnItemClickListener(new DrawerItemClickListener());

        ...
    }
}

处理导航点击事件

 onItemClick()中你做些什么取决于你是怎么实现你的应用结构的。在本文中的实例中,每选择一个list中的item就在主要内容视图中插入一个不同的Fragment:

private class DrawerItemClickListener implements ListView.OnItemClickListener {
    @Override
    public void onItemClick(AdapterView parent, View view, int position, long id) {
        selectItem(position);
    }
}

/** Swaps fragments in the main content view */
private void selectItem(int position) {
    // Create a new fragment and specify the planet to show based on position
    Fragment fragment = new PlanetFragment();
    Bundle args = new Bundle();
    args.putInt(PlanetFragment.ARG_PLANET_NUMBER, position);
    fragment.setArguments(args);

    // Insert the fragment by replacing any existing fragment
    FragmentManager fragmentManager = getFragmentManager();
    fragmentManager.beginTransaction()
                   .replace(R.id.content_frame, fragment)
                   .commit();

    // Highlight the selected item, update the title, and close the drawer
    mDrawerList.setItemChecked(position, true);
    setTitle(mPlanetTitles[position]);
    mDrawerLayout.closeDrawer(mDrawerList);
}

@Override
public void setTitle(CharSequence title) {
    mTitle = title;
    getActionBar().setTitle(mTitle);
}

监听抽屉的开启和关闭事件

为了监听抽屉的开启和关闭事件,通过   setDrawerListener()给 DrawerLayout设置 DrawerLayout.DrawerListener监听器,实现 DrawerLayout.DrawerListener中的回调方法onDrawerOpened() 和 onDrawerClosed()。
但是,假如你的activity包含有actiion bar,你就应该使用ActionBarDrawerToggle(DrawerListener的子类),因为它可以促进action bar和navigation drawer之间的交互。

public class MainActivity extends Activity {
    private DrawerLayout mDrawerLayout;
    private ActionBarDrawerToggle mDrawerToggle;
    private CharSequence mDrawerTitle;
    private CharSequence mTitle;
    ...

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        ...

        mTitle = mDrawerTitle = getTitle();
        mDrawerLayout = (DrawerLayout) findViewById(R.id.drawer_layout);
        mDrawerToggle = new ActionBarDrawerToggle(this, mDrawerLayout,
                R.drawable.ic_drawer, R.string.drawer_open, R.string.drawer_close) {

            /** Called when a drawer has settled in a completely closed state. */
            public void onDrawerClosed(View view) {
                getActionBar().setTitle(mTitle);
                invalidateOptionsMenu(); // creates call to onPrepareOptionsMenu()
            }

            /** Called when a drawer has settled in a completely open state. */
            public void onDrawerOpened(View drawerView) {
                getActionBar().setTitle(mDrawerTitle);
                invalidateOptionsMenu(); // creates call to onPrepareOptionsMenu()
            }
        };

        // Set the drawer toggle as the DrawerListener
        mDrawerLayout.setDrawerListener(mDrawerToggle);
    }

    /* Called whenever we call invalidateOptionsMenu() */
    @Override
    public boolean onPrepareOptionsMenu(Menu menu) {
        // If the nav drawer is open, hide action items related to the content view
        boolean drawerOpen = mDrawerLayout.isDrawerOpen(mDrawerList);
        menu.findItem(R.id.action_websearch).setVisible(!drawerOpen);
        return super.onPrepareOptionsMenu(menu);
    }
}

The next section describes the ActionBarDrawerToggle constructor arguments and the other steps required to set it up to handle interaction with the action bar icon.

通过App Icon开启和关闭抽屉

当有action bar时,你就应该实现可以通过App icon来开启和关闭抽屉。而且这个app icon能够预示抽屉是否存在。
创建一个ActionBarDrawerToggle,它的构造函数需要如下参数:
  • The Activity hosting the drawer.
  • The DrawerLayout.
  • A drawable resource to use as the drawer indicator.The standard navigation drawer icon is available in the Download the Action Bar Icon Pack.
  • A String resource to describe the "open drawer" action (for 人性化).
  • A String resource to describe the "close drawer" action (for 人性化).
  • public class MainActivity extends Activity {
        private DrawerLayout mDrawerLayout;
        private ActionBarDrawerToggle mDrawerToggle;
        ...
    
        public void onCreate(Bundle savedInstanceState) {
            ...
    
            mDrawerLayout = (DrawerLayout) findViewById(R.id.drawer_layout);
            mDrawerToggle = new ActionBarDrawerToggle(
                    this,                  /* host Activity */
                    mDrawerLayout,         /* DrawerLayout object */
                    R.drawable.ic_drawer,  /* nav drawer icon to replace 'Up' caret */
                    R.string.drawer_open,  /* "open drawer" description */
                    R.string.drawer_close  /* "close drawer" description */
                    ) {
    
                /** Called when a drawer has settled in a completely closed state. */
                public void onDrawerClosed(View view) {
                    getActionBar().setTitle(mTitle);
                }
    
                /** Called when a drawer has settled in a completely open state. */
                public void onDrawerOpened(View drawerView) {
                    getActionBar().setTitle(mDrawerTitle);
                }
            };
    
            // Set the drawer toggle as the DrawerListener
            mDrawerLayout.setDrawerListener(mDrawerToggle);
    
            getActionBar().setDisplayHomeAsUpEnabled(true);
            getActionBar().setHomeButtonEnabled(true);
        }
    
        @Override
        protected void onPostCreate(Bundle savedInstanceState) {
            super.onPostCreate(savedInstanceState);
            // Sync the toggle state after onRestoreInstanceState has occurred.
            mDrawerToggle.syncState();
        }
    
        @Override
        public void onConfigurationChanged(Configuration newConfig) {
            super.onConfigurationChanged(newConfig);
            mDrawerToggle.onConfigurationChanged(newConfig);
        }
    
        @Override
        public boolean onOptionsItemSelected(MenuItem item) {
            // Pass the event to ActionBarDrawerToggle, if it returns
            // true, then it has handled the app icon touch event
            if (mDrawerToggle.onOptionsItemSelected(item)) {
              return true;
            }
            // Handle your other action bar items...
    
            return super.onOptionsItemSelected(item);
        }
    
        ...
    }

    点击ActionBar上的Action

    Activity中有两个菜单相关的回调方法:onCreateOptionsMenu(Menu menu)和onPrepareOptionsMenu(Menu menu)

    onCreateOptionsMenu方法:从App创建到结束只会被调用一次,用来初始化Activity的标准选项菜单的内容;当我们需要更新菜单的显示时这个方法明显帮不上什么忙了。

    onPrepareOptionsMenu方法:准备屏幕的标准选项菜单,在菜单显示前调用,而且是每次显示前都会被调用,所有这个方法常用来动态改变菜单项

    关于UP标签的问题

    刚开始在ActionBarDrawerToggle的构造函数中第三个参数设置了UP图标的,但是发现没有起到作用。
    listener = new ActionBarDrawerToggle(
    				this, mDrawerLayout, R.drawable.ic_drawer, R.string.drawer_open, R.string.drawer_close){
    					@Override
    					public void onDrawerClosed(View drawerView) {
    						// title改为mTitle
    						getActionBar().setTitle(mTitle);
    						// 通知修改action bar中的菜单
    						invalidateOptionsMenu();
    					}
    					@Override
    					public void onDrawerOpened(View drawerView) {
    						// title改为mDrawerTitle
    						getActionBar().setTitle(mDrawerTitle);
    						// 通知修改action bar中的菜单
    						invalidateOptionsMenu();
    					}
    		};

    后来才发现 ActionBarDrawerToggle还有个 syncState()方法,作用是同步drawer指示器。  


    你可能感兴趣的:(Navigation,Drawer)