1 /* 2 * Copyright (C) 2013 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 18 package com.example.android.supportv4.widget; 19 20 import android.app.ActionBar; 21 import android.app.Activity; 22 import android.content.res.Configuration; 23 import android.os.Build; 24 import android.os.Bundle; 25 import android.support.v4.app.ActionBarDrawerToggle; 26 import android.support.v4.view.GravityCompat; 27 import android.support.v4.widget.DrawerLayout; 28 import android.view.Gravity; 29 import android.view.MenuItem; 30 import android.view.View; 31 import android.widget.AdapterView; 32 import android.widget.ArrayAdapter; 33 import android.widget.ListView; 34 import android.widget.TextView; 35 import com.example.android.supportv4.R; 36 import com.example.android.supportv4.Shakespeare; 37 38 /** 39 * This example illustrates a common usage of the DrawerLayout widget 40 * in the Android support library. 41 * 42 * <p>A DrawerLayout should be positioned at the top of your view hierarchy, placing it 43 * below the action bar but above your content views. The primary content should match_parent 44 * in both dimensions. Each drawer should define a reasonable width and match_parent for height. 45 * Drawer views should be positioned after the content view in your layout to preserve proper 46 * ordering.</p> 47 * 48 * <p>When a navigation (left) drawer is present, the host activity should detect presses of 49 * the action bar's Up affordance as a signal to open and close the navigation drawer. 50 * Items within the drawer should fall into one of two categories.</p> 51 * 52 * <ul> 53 * <li><strong>View switches</strong>. A view switch follows the same basic policies as 54 * list or tab navigation in that a view switch does not create navigation history. 55 * This pattern should only be used at the root activity of a task, leaving some form 56 * of Up navigation active for activities further down the navigation hierarchy.</li> 57 * <li><strong>Selective Up</strong>. The drawer allows the user to choose an alternate 58 * parent for Up navigation. This allows a user to jump across an app's navigation 59 * hierarchy at will. The application should treat this as it treats Up navigation from 60 * a different task, replacing the current task stack using TaskStackBuilder or similar. 61 * This is the only form of navigation drawer that should be used outside of the root 62 * activity of a task.</li> 63 * </ul> 64 * 65 * <p>Right side drawers should be used for actions, not navigation. This follows the pattern 66 * established by the Action Bar that navigation should be to the left and actions to the right. 67 * An action should be an operation performed on the current contents of the window, 68 * for example enabling or disabling a data overlay on top of the current content.</p> 69 */ 70 public class DrawerLayoutActivity extends Activity { 71 private DrawerLayout mDrawerLayout; 72 private ListView mDrawer; 73 private TextView mContent; 74 75 private ActionBarHelper mActionBar; 76 77 private ActionBarDrawerToggle mDrawerToggle; 78 79 @Override 80 protected void onCreate(Bundle savedInstanceState) { 81 super.onCreate(savedInstanceState); 82 83 setContentView(R.layout.drawer_layout); 84 85 mDrawerLayout = (DrawerLayout) findViewById(R.id.drawer_layout); 86 mDrawer = (ListView) findViewById(R.id.start_drawer); 87 mContent = (TextView) findViewById(R.id.content_text); 88 89 mDrawerLayout.setDrawerListener(new DemoDrawerListener()); 90 mDrawerLayout.setDrawerShadow(R.drawable.drawer_shadow, GravityCompat.START); 91 92 // The drawer title must be set in order to announce state changes when 93 // accessibility is turned on. This is typically a simple description, 94 // e.g. "Navigation". 95 mDrawerLayout.setDrawerTitle(GravityCompat.START, getString(R.string.drawer_title)); 96 97 mDrawer.setAdapter(new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, 98 Shakespeare.TITLES)); 99 mDrawer.setOnItemClickListener(new DrawerItemClickListener()); 100 101 mActionBar = createActionBarHelper(); 102 mActionBar.init(); 103 104 // ActionBarDrawerToggle provides convenient helpers for tying together the 105 // prescribed interactions between a top-level sliding drawer and the action bar. 106 mDrawerToggle = new ActionBarDrawerToggle(this, mDrawerLayout, 107 R.drawable.ic_drawer, R.string.drawer_open, R.string.drawer_close); 108 } 109 110 @Override 111 protected void onPostCreate(Bundle savedInstanceState) { 112 super.onPostCreate(savedInstanceState); 113 114 // Sync the toggle state after onRestoreInstanceState has occurred. 115 mDrawerToggle.syncState(); 116 } 117 118 @Override 119 public boolean onOptionsItemSelected(MenuItem item) { 120 /* 121 * The action bar home/up action should open or close the drawer. 122 * mDrawerToggle will take care of this. 123 */ 124 if (mDrawerToggle.onOptionsItemSelected(item)) { 125 return true; 126 } 127 return super.onOptionsItemSelected(item); 128 } 129 130 @Override 131 public void onConfigurationChanged(Configuration newConfig) { 132 super.onConfigurationChanged(newConfig); 133 mDrawerToggle.onConfigurationChanged(newConfig); 134 } 135 136 /** 137 * This list item click listener implements very simple view switching by changing 138 * the primary content text. The drawer is closed when a selection is made. 139 */ 140 private class DrawerItemClickListener implements ListView.OnItemClickListener { 141 @Override 142 public void onItemClick(AdapterView<?> parent, View view, int position, long id) { 143 mContent.setText(Shakespeare.DIALOGUE[position]); 144 mActionBar.setTitle(Shakespeare.TITLES[position]); 145 mDrawerLayout.closeDrawer(mDrawer); 146 } 147 } 148 149 /** 150 * A drawer listener can be used to respond to drawer events such as becoming 151 * fully opened or closed. You should always prefer to perform expensive operations 152 * such as drastic relayout when no animation is currently in progress, either before 153 * or after the drawer animates. 154 * 155 * When using ActionBarDrawerToggle, all DrawerLayout listener methods should be forwarded 156 * if the ActionBarDrawerToggle is not used as the DrawerLayout listener directly. 157 */ 158 private class DemoDrawerListener implements DrawerLayout.DrawerListener { 159 @Override 160 public void onDrawerOpened(View drawerView) { 161 mDrawerToggle.onDrawerOpened(drawerView); 162 mActionBar.onDrawerOpened(); 163 } 164 165 @Override 166 public void onDrawerClosed(View drawerView) { 167 mDrawerToggle.onDrawerClosed(drawerView); 168 mActionBar.onDrawerClosed(); 169 } 170 171 @Override 172 public void onDrawerSlide(View drawerView, float slideOffset) { 173 mDrawerToggle.onDrawerSlide(drawerView, slideOffset); 174 } 175 176 @Override 177 public void onDrawerStateChanged(int newState) { 178 mDrawerToggle.onDrawerStateChanged(newState); 179 } 180 } 181 182 /** 183 * Create a compatible helper that will manipulate the action bar if available. 184 */ 185 private ActionBarHelper createActionBarHelper() { 186 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH) { 187 return new ActionBarHelperICS(); 188 } else { 189 return new ActionBarHelper(); 190 } 191 } 192 193 /** 194 * Stub action bar helper; this does nothing. 195 */ 196 private class ActionBarHelper { 197 public void init() {} 198 public void onDrawerClosed() {} 199 public void onDrawerOpened() {} 200 public void setTitle(CharSequence title) {} 201 } 202 203 /** 204 * Action bar helper for use on ICS and newer devices. 205 */ 206 private class ActionBarHelperICS extends ActionBarHelper { 207 private final ActionBar mActionBar; 208 private CharSequence mDrawerTitle; 209 private CharSequence mTitle; 210 211 ActionBarHelperICS() { 212 mActionBar = getActionBar(); 213 } 214 215 @Override 216 public void init() { 217 mActionBar.setDisplayHomeAsUpEnabled(true); 218 mActionBar.setHomeButtonEnabled(true); 219 mTitle = mDrawerTitle = getTitle(); 220 } 221 222 /** 223 * When the drawer is closed we restore the action bar state reflecting 224 * the specific contents in view. 225 */ 226 @Override 227 public void onDrawerClosed() { 228 super.onDrawerClosed(); 229 mActionBar.setTitle(mTitle); 230 } 231 232 /** 233 * When the drawer is open we set the action bar to a generic title. 234 * The action bar should only contain data relevant at the top level of 235 * the nav hierarchy represented by the drawer, as the rest of your content 236 * will be dimmed down and non-interactive. 237 */ 238 @Override 239 public void onDrawerOpened() { 240 super.onDrawerOpened(); 241 mActionBar.setTitle(mDrawerTitle); 242 } 243 244 @Override 245 public void setTitle(CharSequence title) { 246 mTitle = title; 247 } 248 } 249 } 250