summaryrefslogtreecommitdiff
path: root/docs/html/training/implementing-navigation/nav-drawer.jd
diff options
context:
space:
mode:
Diffstat (limited to 'docs/html/training/implementing-navigation/nav-drawer.jd')
-rw-r--r--docs/html/training/implementing-navigation/nav-drawer.jd368
1 files changed, 368 insertions, 0 deletions
diff --git a/docs/html/training/implementing-navigation/nav-drawer.jd b/docs/html/training/implementing-navigation/nav-drawer.jd
new file mode 100644
index 000000000000..da2b04614b0d
--- /dev/null
+++ b/docs/html/training/implementing-navigation/nav-drawer.jd
@@ -0,0 +1,368 @@
+page.title=Creating a Navigation Drawer
+
+trainingnavtop=true
+
+@jd:body
+
+<div id="tb-wrapper">
+<div id="tb">
+
+<h2>This lesson teaches you to:</h2>
+<ol>
+ <li><a href="#DrawerLayout">Create a Drawer Layout</a></li>
+ <li><a href="#Init">Initialize the Drawer List</a></li>
+ <li><a href="#ListItemClicks">Handle Navigation Click Events</a></li>
+ <li><a href="#OpenClose">Listen for Open and Close Events</a></li>
+ <li><a href="#ActionBarIcon">Open and Close with the App Icon</a></li>
+</ol>
+
+<h2>Try it out</h2>
+
+<div class="download-box">
+<a href="http://developer.android.com/shareables/training/NavigationDrawer.zip"
+ class="button">Download the sample app</a>
+<p class="filename">NavigationDrawer.zip</p>
+</div>
+
+</div>
+</div>
+
+
+
+<p>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.</p>
+
+<p>This lesson describes how to implement a navigation drawer using the
+{@link android.support.v4.widget.DrawerLayout} APIs available in the
+<a href="{@docRoot}tools/extras/support-library.html">Support Library</a>.</p>
+
+<div class="note design">
+<p><strong>Navigation Drawer Design</strong></p>
+<p>Before you decide to use a navigation drawer in your app, you should understand the use
+cases and design principles defined in the
+<a href="{@docRoot}design/patterns/navigation-drawers.html">Navigation Drawer</a> design guide.</p>
+</div>
+
+
+<h2 id="DrawerLayout">Create a Drawer Layout</h2>
+
+<p>To add a navigation drawer, declare your user interface with a
+{@link android.support.v4.widget.DrawerLayout} object as the root view of your layout.
+Inside the {@link android.support.v4.widget.DrawerLayout}, 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.</p>
+
+<p>For example, the following layout uses a {@link
+android.support.v4.widget.DrawerLayout} with two child views: a {@link android.widget.FrameLayout}
+to contain the main content (populated by a {@link android.app.Fragment} at
+runtime), and a {@link android.widget.ListView} for the navigation drawer.</p>
+
+<pre>
+&lt;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">
+ &lt;!-- The main content view -->
+ &lt;FrameLayout
+ android:id="@+id/content_frame"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent" />
+ &lt;!-- The navigation drawer -->
+ &lt;ListView android:id="@+id/left_drawer"
+ android:layout_width="240dp"
+ android:layout_height="match_parent"
+ android:layout_gravity="start"
+ android:choiceMode="singleChoice"
+ android:divider="&#64;android:color/transparent"
+ android:dividerHeight="0dp"
+ android:background="#111"/>
+&lt;/android.support.v4.widget.DrawerLayout>
+</pre>
+
+<p>This layout demonstrates some important layout characteristics:</p>
+<ul>
+ <li>The main content view (the {@link android.widget.FrameLayout} above)
+ <strong>must be the first child</strong> in the {@link
+ android.support.v4.widget.DrawerLayout} because the XML order implies z-ordering
+ and the drawer must be on top of the content.</li>
+ <li>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.</li>
+ <li>The drawer view (the {@link android.widget.ListView}) <strong>must specify its horizontal
+ gravity</strong> with the {@code android:layout_gravity} attribute. To
+ support right-to-left (RTL) languages, specify the value with {@code "start"}
+ instead of {@code "left"} (so the drawer appears on the right when the layout is RTL).</p>
+ </li>
+ <li>The drawer view specifies its width in {@code 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.</li>
+</ul>
+
+
+
+<h2 id="Init">Initialize the Drawer List</h2>
+
+<p>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 {@link android.widget.ListView}, so the list
+should be populated by an {@link android.widget.Adapter} (such as {@link
+android.widget.ArrayAdapter} or {@link android.widget.SimpleCursorAdapter}).</p>
+
+<p>For example, here's how you can initialize the navigation list with a
+<a href="{@docRoot}guide/topics/resources/string-resource.html#StringArray">string array</a>:</p>
+
+<pre>
+public class MainActivity extends Activity {
+ private String[] mPlanetTitles;
+ private ListView mDrawerList;
+ ...
+
+ &#64;Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.activity_main);
+
+ mPlanetTitles = getResources().getStringArray(R.array.planets_array);
+ mDrawerList = (ListView) findViewById(R.id.left_drawer);
+
+ // Set the adapter for the list view
+ mDrawerList.setAdapter(new ArrayAdapter&lt;String>(this,
+ R.layout.drawer_list_item, mPlanetTitles));
+ // Set the list's click listener
+ mDrawerList.setOnItemClickListener(new DrawerItemClickListener());
+
+ ...
+ }
+}
+</pre>
+
+<p>This code also calls {@link android.widget.ListView#setOnItemClickListener
+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.</p>
+
+
+
+<h2 id="ListItemClicks">Handle Navigation Click Events</h2>
+
+<p>When the user selects an item in the drawer's list, the system calls {@link
+android.widget.AdapterView.OnItemClickListener#onItemClick onItemClick()} on the
+{@link android.widget.AdapterView.OnItemClickListener OnItemClickListener} given to
+{@link android.widget.ListView#setOnItemClickListener setOnItemClickListener()}.</p>
+
+<p>What you do in the {@link
+android.widget.AdapterView.OnItemClickListener#onItemClick onItemClick()} method
+depends on how you've implemented your <a
+href="{@docRoot}design/patterns/app-structure.html">app structure</a>. In the following example,
+selecting each item in the list inserts a different {@link
+android.app.Fragment} into the main content view (the
+{@link android.widget.FrameLayout} element identified by the {@code R.id.content_frame} ID):</p>
+
+<pre>
+private class DrawerItemClickListener implements ListView.OnItemClickListener {
+ &#64;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
+ mDrawer.setItemChecked(position, true);
+ setTitle(mPlanetTitles[position]);
+ mDrawerLayout.closeDrawer(mDrawer);
+}
+
+&#64;Override
+public void setTitle(CharSequence title) {
+ mTitle = title;
+ getActionBar().setTitle(mTitle);
+}
+
+</pre>
+
+
+
+
+<h2 id="OpenClose">Listen for Open and Close Events</h2>
+
+<p>To listen for drawer open and close events, call {@link
+android.support.v4.widget.DrawerLayout#setDrawerListener setDrawerListener()} on your
+{@link android.support.v4.widget.DrawerLayout} and pass it an implementation of
+{@link android.support.v4.widget.DrawerLayout.DrawerListener}. This interface provides callbacks
+for drawer events such as {@link
+android.support.v4.widget.DrawerLayout.DrawerListener#onDrawerOpened onDrawerOpened()} and {@link
+android.support.v4.widget.DrawerLayout.DrawerListener#onDrawerClosed onDrawerClosed()}.</p>
+
+<p>However, rather than implementing the {@link
+android.support.v4.widget.DrawerLayout.DrawerListener}, if your activity includes the
+<a href="{@docRoot}guide/topics/ui/actionbar.html">action bar</a>, you can instead
+extend the {@link android.support.v4.app.ActionBarDrawerToggle} class. The
+{@link android.support.v4.app.ActionBarDrawerToggle} implements
+{@link android.support.v4.widget.DrawerLayout.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).</p>
+
+<p>As discussed in the <a href="{@docRoot}design/patterns/navigation-drawers.html">Navigation
+Drawer</a> 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 {@link
+android.support.v4.widget.DrawerLayout.DrawerListener} callback methods with an instance
+of the {@link android.support.v4.app.ActionBarDrawerToggle} class:</p>
+
+<pre>
+public class MainActivity extends Activity {
+ private DrawerLayout mDrawerLayout;
+ private ActionBarDrawerToggle mDrawerToggle;
+ private CharSequence mDrawerTitle;
+ private CharSequence mTitle;
+ ...
+
+ &#64;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() */
+ &#64;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);
+ }
+}
+</pre>
+
+<p>The next section describes the {@link android.support.v4.app.ActionBarDrawerToggle} constructor
+arguments and the other steps required to set it up to handle interaction with the
+action bar icon.</p>
+
+
+
+<h2 id="ActionBarIcon">Open and Close with the App Icon</h2>
+
+<p>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 <a
+href="{@docRoot}guide/topics/ui/actionbar.html">action bar</a>, 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
+{@link android.support.v4.app.ActionBarDrawerToggle} shown in the previous section.</p>
+
+<p>To make {@link android.support.v4.app.ActionBarDrawerToggle} work, create an instance of
+it with its constructor, which requires the following arguments:</p>
+<ul>
+ <li>The {@link android.app.Activity} hosting the drawer.
+ <li>The {@link android.support.v4.widget.DrawerLayout}.
+ <li>A drawable resource to use as the drawer indicator.
+ <li>A String resource to describe the "open drawer" action (for accessibility).
+ <li>A String resource to describe the "close drawer" action (for accessibility).
+</ul>
+
+<p>Then, whether or not you've created a subclass of
+{@link android.support.v4.app.ActionBarDrawerToggle} as your drawer listener, you need to call
+upon your {@link android.support.v4.app.ActionBarDrawerToggle} in a few places throughout your
+activity lifecycle:</p>
+
+<pre>
+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, 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);
+ }
+
+ /** 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);
+ }
+
+ &#64;Override
+ protected void onPostCreate(Bundle savedInstanceState) {
+ super.onPostCreate(savedInstanceState);
+ // Sync the toggle state after onRestoreInstanceState has occurred.
+ mDrawerToggle.syncState();
+ }
+
+ &#64;Override
+ public void onConfigurationChanged(Configuration newConfig) {
+ super.onConfigurationChanged(newConfig);
+ mDrawerToggle.onConfigurationChanged(newConfig);
+ }
+
+ &#64;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);
+ }
+
+ ...
+}
+</pre>
+
+<p>For a complete example of a navigation drawer, download the sample available at the
+<a href="#top">top of the page</a>.</p> \ No newline at end of file