/* * Copyright (C) 2013 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.example.android.supportv4.widget; import android.app.ActionBar; import android.app.Activity; import android.content.res.Configuration; import android.os.Build; import android.os.Bundle; import android.support.v4.app.ActionBarDrawerToggle; import android.support.v4.view.GravityCompat; import android.support.v4.widget.DrawerLayout; import android.view.Gravity; import android.view.MenuItem; import android.view.View; import android.widget.AdapterView; import android.widget.ArrayAdapter; import android.widget.ListView; import android.widget.TextView; import com.example.android.supportv4.R; import com.example.android.supportv4.Shakespeare; /** * This example illustrates a common usage of the DrawerLayout widget * in the Android support library. * * <p>A DrawerLayout should be positioned at the top of your view hierarchy, placing it * below the action bar but above your content views. The primary content should match_parent * in both dimensions. Each drawer should define a reasonable width and match_parent for height. * Drawer views should be positioned after the content view in your layout to preserve proper * ordering.</p> * * <p>When a navigation (left) drawer is present, the host activity should detect presses of * the action bar's Up affordance as a signal to open and close the navigation drawer. * Items within the drawer should fall into one of two categories.</p> * * <ul> * <li><strong>View switches</strong>. A view switch follows the same basic policies as * list or tab navigation in that a view switch does not create navigation history. * This pattern should only be used at the root activity of a task, leaving some form * of Up navigation active for activities further down the navigation hierarchy.</li> * <li><strong>Selective Up</strong>. The drawer allows the user to choose an alternate * parent for Up navigation. This allows a user to jump across an app's navigation * hierarchy at will. The application should treat this as it treats Up navigation from * a different task, replacing the current task stack using TaskStackBuilder or similar. * This is the only form of navigation drawer that should be used outside of the root * activity of a task.</li> * </ul> * * <p>Right side drawers should be used for actions, not navigation. This follows the pattern * established by the Action Bar that navigation should be to the left and actions to the right. * An action should be an operation performed on the current contents of the window, * for example enabling or disabling a data overlay on top of the current content.</p> */ public class DrawerLayoutActivity extends Activity { private DrawerLayout mDrawerLayout; private ListView mDrawer; private TextView mContent; private ActionBarHelper mActionBar; private ActionBarDrawerToggle mDrawerToggle; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.drawer_layout); mDrawerLayout = (DrawerLayout) findViewById(R.id.drawer_layout); mDrawer = (ListView) findViewById(R.id.start_drawer); mContent = (TextView) findViewById(R.id.content_text); mDrawerLayout.setDrawerListener(new DemoDrawerListener()); mDrawerLayout.setDrawerShadow(R.drawable.drawer_shadow, GravityCompat.START); // The drawer title must be set in order to announce state changes when // accessibility is turned on. This is typically a simple description, // e.g. "Navigation". mDrawerLayout.setDrawerTitle(GravityCompat.START, getString(R.string.drawer_title)); mDrawer.setAdapter(new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, Shakespeare.TITLES)); mDrawer.setOnItemClickListener(new DrawerItemClickListener()); mActionBar = createActionBarHelper(); mActionBar.init(); // ActionBarDrawerToggle provides convenient helpers for tying together the // prescribed interactions between a top-level sliding drawer and the action bar. mDrawerToggle = new ActionBarDrawerToggle(this, mDrawerLayout, R.drawable.ic_drawer, R.string.drawer_open, R.string.drawer_close); } @Override protected void onPostCreate(Bundle savedInstanceState) { super.onPostCreate(savedInstanceState); // Sync the toggle state after onRestoreInstanceState has occurred. mDrawerToggle.syncState(); } @Override public boolean onOptionsItemSelected(MenuItem item) { /* * The action bar home/up action should open or close the drawer. * mDrawerToggle will take care of this. */ if (mDrawerToggle.onOptionsItemSelected(item)) { return true; } return super.onOptionsItemSelected(item); } @Override public void onConfigurationChanged(Configuration newConfig) { super.onConfigurationChanged(newConfig); mDrawerToggle.onConfigurationChanged(newConfig); } /** * This list item click listener implements very simple view switching by changing * the primary content text. The drawer is closed when a selection is made. */ private class DrawerItemClickListener implements ListView.OnItemClickListener { @Override public void onItemClick(AdapterView<?> parent, View view, int position, long id) { mContent.setText(Shakespeare.DIALOGUE[position]); mActionBar.setTitle(Shakespeare.TITLES[position]); mDrawerLayout.closeDrawer(mDrawer); } } /** * A drawer listener can be used to respond to drawer events such as becoming * fully opened or closed. You should always prefer to perform expensive operations * such as drastic relayout when no animation is currently in progress, either before * or after the drawer animates. * * When using ActionBarDrawerToggle, all DrawerLayout listener methods should be forwarded * if the ActionBarDrawerToggle is not used as the DrawerLayout listener directly. */ private class DemoDrawerListener implements DrawerLayout.DrawerListener { @Override public void onDrawerOpened(View drawerView) { mDrawerToggle.onDrawerOpened(drawerView); mActionBar.onDrawerOpened(); } @Override public void onDrawerClosed(View drawerView) { mDrawerToggle.onDrawerClosed(drawerView); mActionBar.onDrawerClosed(); } @Override public void onDrawerSlide(View drawerView, float slideOffset) { mDrawerToggle.onDrawerSlide(drawerView, slideOffset); } @Override public void onDrawerStateChanged(int newState) { mDrawerToggle.onDrawerStateChanged(newState); } } /** * Create a compatible helper that will manipulate the action bar if available. */ private ActionBarHelper createActionBarHelper() { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH) { return new ActionBarHelperICS(); } else { return new ActionBarHelper(); } } /** * Stub action bar helper; this does nothing. */ private class ActionBarHelper { public void init() {} public void onDrawerClosed() {} public void onDrawerOpened() {} public void setTitle(CharSequence title) {} } /** * Action bar helper for use on ICS and newer devices. */ private class ActionBarHelperICS extends ActionBarHelper { private final ActionBar mActionBar; private CharSequence mDrawerTitle; private CharSequence mTitle; ActionBarHelperICS() { mActionBar = getActionBar(); } @Override public void init() { mActionBar.setDisplayHomeAsUpEnabled(true); mActionBar.setHomeButtonEnabled(true); mTitle = mDrawerTitle = getTitle(); } /** * When the drawer is closed we restore the action bar state reflecting * the specific contents in view. */ @Override public void onDrawerClosed() { super.onDrawerClosed(); mActionBar.setTitle(mTitle); } /** * When the drawer is open we set the action bar to a generic title. * The action bar should only contain data relevant at the top level of * the nav hierarchy represented by the drawer, as the rest of your content * will be dimmed down and non-interactive. */ @Override public void onDrawerOpened() { super.onDrawerOpened(); mActionBar.setTitle(mDrawerTitle); } @Override public void setTitle(CharSequence title) { mTitle = title; } } }