Creating a Navigation Drawerandroid
PreviousNextweb
This lesson teaches you to:app
Create a Drawer Layoutless
Initialize the Drawer Listide
Handle Navigation Click Events佈局
Listen for Open and Close Eventsui
Open and Close with the App Iconthis
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, the user touches the app icon in the action bar.spa
導航抽屜式一個顯示應用程序的主要導航選項的面板,它顯示在屏幕的左邊。在大部分時間內它是隱藏狀態的,當用戶用一直手指從屏幕的左邊緣滑動時,導航抽屜就會顯示出來。或者在棧頂的應用程序,用戶在操做欄觸摸應用程序的圖標時,它也會顯示出來。 設計
This lesson describes how to implement a navigation drawer using the DrawerLayout APIs available in the Support Library.
本段描述如何使用支持庫中的DrawerLayout 的APIS 去實現一個導航抽屜
Navigation Drawer Design
Before you decide to use a navigation drawer in your app, you should understand the use cases and design principles defined in the Navigation Drawer design guide.
在你決定在你的應用程序中使用一個導航抽屜前,你應該瞭解在Navigation Drawer 設計指導中的使用案例和設計規則。
Create a Drawer Layout
建立一個抽屜佈局
To add a navigation drawer, declare your user interface with aDrawerLayout object as the root view of your layout. Inside theDrawerLayout, add one view that contains the main content for the screen (your primary layout when the drawer is hidden) and another view that contains the contents of the navigation drawer.
添加一個導航抽屜,你須要將你的用戶界面用一個DrawerLayout 對象做爲你佈局文件的根視圖。DrawerLayout添加一個包含主要文本的視圖,該文本視圖爲在屏幕中主要去顯示文本內容。在抽屜隱藏時,該視圖也是你的主要佈局。另一個視圖包含了導航抽屜裏的內容視圖
For example, the following layout uses a DrawerLayout with two child views: a FrameLayout to contain the main content (populated by a Fragment at runtime), and a ListView for the 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>
This layout demonstrates some important layout characteristics:
上面的佈局示範了一些重要的佈局特徵
The main content view (the FrameLayout above) must be the first child in the DrawerLayout because the XML order implies z-ordering and the drawer must be on top of the content.
在DrawerLayout中,主文本視圖必須是第一個字視圖。由於xml的執行順序意味着Z軸和抽屜必須在文本的頂部
The main content view is set to match the parent view's width and height, because it represents the entire UI when the navigation drawer is hidden.
主文本視圖的寬高設置爲匹配父窗體。由於在抽屜處於隱藏狀態下進入UI界面時做爲主要的視圖。
The drawer view (the ListView) must specify its horizontal gravity with the android:layout_gravityattribute. To support right-to-left (RTL) languages, specify the value with "start" instead of "left" (so the drawer appears on the right when the layout is RTL).
抽屜視圖必須制定是水平方向的listView。制定start代替left
The drawer view specifies its width in dp units and the height matches the parent view. The drawer width should be no more than 320dp so the user can always see a portion of the main content.
抽屜視圖制定的寬是按dp爲代碼計算高匹配父窗體。抽屜的寬應該不超過320dp一邊用戶能夠一直看到主文本的一部分
Initialize the Drawer List
In your activity, one of the first things to do is initialize the navigation drawer's list of items. How you do so depends on the content of your app, but a navigation drawer often consists of a ListView, so the list should be populated by an Adapter (such as ArrayAdapter or SimpleCursorAdapter).
在你的activity中,第一件事情應該是初始化這個導航抽屜的列表項。如何去實現取決於你的應用程序的內容。可是一個導航抽屜一般由一個listView構成,因此若是你使用listView的話應該給它填充一個適配器
For example, here's how you can initialize the navigation list with a string array:
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());
...
}
}
This code also calls setOnItemClickListener() to receive click events in the navigation drawer's list. The next section shows how to implement this interface and change the content view when the user selects an item.
Handle Navigation Click Events
When the user selects an item in the drawer's list, the system calls , android.view.View, int, long)">onItemClick() on theOnItemClickListener given to setOnItemClickListener().
當用戶在抽屜列表中選擇一個項時,系統在OnItemClickListener的onItemClick方法
What you do in the , android.view.View, int, long)">onItemClick() method depends on how you've implemented your app structure. In the following example, selecting each item in the list inserts a different Fragment into the main content view (theFrameLayout element identified by the R.id.content_frame ID):
在onItemClick方法中作什麼取決於你如何實現你的應用程序結構。下面的例子演示選擇每個項都插入一個不一樣的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);
}
Listen for Open and Close Events
監聽打開或者關閉事件
To listen for drawer open and close events, call setDrawerListener() on your DrawerLayout and pass it an implementation of DrawerLayout.DrawerListener. This interface provides callbacks for drawer events such asonDrawerOpened() and onDrawerClosed().
在你的DrawerLayout中調用setDrawerListener去監聽抽屜的打開或者關閉事件。你能夠實現DrawerLayout.DrawerListener.去達到以上操做的目的。該接口提供了抽屜事件的回調方法。
However, rather than implementing the DrawerLayout.DrawerListener, if your activity includes the action bar, you can instead extend the ActionBarDrawerToggle class. The ActionBarDrawerToggle implementsDrawerLayout.DrawerListener so you can still override those callbacks, but it also facilitates the proper interaction behavior between the action bar icon and the navigation drawer (discussed further in the next section).
然而,若是你的activity包括了action bar ,你能夠集成ActionBarDrawerToggle類,而不是實現DrawerLayout.DrawerListener。ActionBarDrawerToggle實現了DrawerLayout.DrawerListener一邊你仍然能夠重寫那些回調方法,可是這樣有助於完善操做欄圖標和導航抽屜的交互行爲(將在下一章節討論。
As discussed in the Navigation Drawer design guide, you should modify the contents of the action bar when the drawer is visible, such as to change the title and remove action items that are contextual to the main content. The following code shows how you can do so by overriding DrawerLayout.DrawerListener callback methods with an instance of the ActionBarDrawerToggle class:
正如導航抽屜設置指南中所討論的,在抽屜是可見狀態時,你應該修改action bar的內容,例如改變主要文本上下文的標題或者移除操做項。如下代碼向你展現如何在ActionBarDrawerToggle的實例對象中去覆蓋DrawerLayout.DrawerListener回調方法
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) {
super.onDrawerClosed(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) {
super.onDrawerOpened(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.
下面章節討論ActionBarDrawerToggle的構造參數和其餘的在建立和操做action bar 圖標時的要求的步驟
Open and Close with the App Icon
Users can open and close the navigation drawer with a swipe gesture from or towards the left edge of the screen, but if you're using the action bar, you should also allow users to open and close it by touching the app icon. And the app icon should also indicate the presence of the navigation drawer with a special icon. You can implement all this behavior by using the ActionBarDrawerToggle shown in the previous section.
用戶能夠從屏幕的左邊緣用一個滑動操做打開或者關閉導航抽屜,但若是你使用action bar,你應該容許用戶經過觸摸應用程序圖標打開和關閉導航抽屜。應用突變也應該用一個指定的圖標指明導航抽屜。你經過可使用ActionBarDrawerToggle是實現全部的行爲
To make ActionBarDrawerToggle work, create an instance of it with its constructor, which requires the following arguments:
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 accessibility).
A String resource to describe the "close drawer" action (for accessibility).
Then, whether or not you've created a subclass of ActionBarDrawerToggle as your drawer listener, you need to call upon your ActionBarDrawerToggle in a few places throughout your activity lifecycle:
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) {
super.onDrawerClosed(view);
getActionBar().setTitle(mTitle);
}
/** Called when a drawer has settled in a completely open state. */
public void onDrawerOpened(View drawerView) {
super.onDrawerOpened(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);
}
...
}