1/* 2 * Copyright (C) 2015 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 17package android.support.v7.app; 18 19import android.content.res.Configuration; 20import android.content.res.Resources; 21import android.content.res.TypedArray; 22import android.os.Bundle; 23import android.support.v4.view.GravityCompat; 24import android.support.v4.widget.DrawerLayout; 25import android.support.v7.appcompat.test.R; 26import android.support.v7.testutils.BaseTestActivity; 27import android.support.v7.testutils.Shakespeare; 28import android.support.v7.widget.Toolbar; 29import android.view.MenuItem; 30import android.view.View; 31import android.view.ViewTreeObserver; 32import android.widget.AdapterView; 33import android.widget.ArrayAdapter; 34import android.widget.ListView; 35import android.widget.TextView; 36 37/** 38 * Test activity for testing various APIs and interactions for DrawerLayout. It follows 39 * a common usage of the DrawerLayout widget combined with Toolbar in the Android support library 40 * that respect the 41 * <a href="https://www.google.com/design/spec/patterns/navigation-drawer.html">Material design 42 * guidelines</a> for the drawer component. 43 */ 44public class DrawerLayoutActivity extends BaseTestActivity { 45 private DrawerLayout mDrawerLayout; 46 private ListView mDrawer; 47 private TextView mContent; 48 49 private ActionBarDrawerToggle mDrawerToggle; 50 private Toolbar mToolbar; 51 52 @Override 53 protected int getContentViewLayoutResId() { 54 return R.layout.drawer_layout; 55 } 56 57 @Override 58 protected void onContentViewSet() { 59 super.onContentViewSet(); 60 61 mDrawerLayout = (DrawerLayout) findViewById(R.id.drawer_layout); 62 mDrawer = (ListView) findViewById(R.id.start_drawer); 63 mContent = (TextView) findViewById(R.id.content_text); 64 65 mDrawerLayout.setDrawerShadow(R.drawable.drawer_shadow, GravityCompat.START); 66 67 // The drawer title must be set in order to announce state changes when 68 // accessibility is turned on. This is typically a simple description, 69 // e.g. "Navigation". 70 mDrawerLayout.setDrawerTitle(GravityCompat.START, getString(R.string.drawer_title)); 71 72 mDrawer.setAdapter(new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, 73 Shakespeare.TITLES)); 74 mDrawer.setOnItemClickListener(new DrawerItemClickListener()); 75 76 // Find the toolbar in our layout and set it as the support action bar on the activity. 77 // This is required to have the drawer slide "over" the toolbar. 78 mToolbar = (Toolbar) findViewById(R.id.toolbar); 79 mToolbar.setTitle(R.string.drawer_title); 80 setSupportActionBar(mToolbar); 81 82 getSupportActionBar().setDisplayHomeAsUpEnabled(true); 83 getSupportActionBar().setDisplayShowHomeEnabled(false); 84 85 // ActionBarDrawerToggle provides convenient helpers for tying together the 86 // prescribed interactions between a top-level sliding drawer and the action bar. 87 // Note that, as the Javadocs of ActionBarDrawerToggle constructors say, we are 88 // *not* using a constructor that gets a Toolbar since we're setting our toolbar 89 // dynamically at runtime. Furthermore, as the drawer is sliding over the toolbar, 90 // we are suppressing the morphing animation from hamburger to back arrow by 91 // calling super.onDrawerSlide with slideOffset=0.0f. In case your app only has 92 // top-level pages and doesn't need back arrow visuals at all, you can set up 93 // your activity theme to have attribute named "drawerArrowStyle" that points 94 // to an extension of Widget.AppCompat.DrawerArrowToggle that has its "spinBars" 95 // attribute set to false. 96 mDrawerToggle = new ActionBarDrawerToggle(this, mDrawerLayout, 97 R.string.drawer_open, R.string.drawer_close) { 98 @Override 99 public void onDrawerOpened(View drawerView) { 100 super.onDrawerOpened(drawerView); 101 super.onDrawerSlide(drawerView, 0.0f); 102 } 103 104 @Override 105 public void onDrawerSlide(View drawerView, float slideOffset) { 106 super.onDrawerSlide(drawerView, 0.0f); 107 } 108 }; 109 110 mDrawerLayout.addDrawerListener(mDrawerToggle); 111 112 // Configure the background color fill of the system status bar (on supported platform 113 // versions) and the toolbar itself. We're using the same color, and android:statusBar 114 // from the theme makes the status bar slightly darker. 115 final int metalBlueColor = getResources().getColor(R.color.drawer_sample_metal_blue); 116 mDrawerLayout.setStatusBarBackgroundColor(metalBlueColor); 117 mToolbar.setBackgroundColor(metalBlueColor); 118 119 // Register a pre-draw listener to get the initial width of the DrawerLayout so 120 // that we can determine the width of the drawer based on the Material spec at 121 // https://www.google.com/design/spec/patterns/navigation-drawer.html#navigation-drawer-specs 122 mDrawerLayout.getViewTreeObserver().addOnPreDrawListener( 123 new ViewTreeObserver.OnPreDrawListener() { 124 @Override 125 public boolean onPreDraw() { 126 // What is the width of the entire DrawerLayout? 127 final int drawerLayoutWidth = mDrawerLayout.getWidth(); 128 129 // What is the action bar size? 130 final Resources.Theme theme = mDrawerLayout.getContext().getTheme(); 131 final TypedArray a = theme.obtainStyledAttributes( 132 new int[] { android.support.v7.appcompat.R.attr.actionBarSize }); 133 final int actionBarSize = a.getDimensionPixelSize(0, 0); 134 if (a != null) { 135 a.recycle(); 136 } 137 138 // Compute the width of the drawer and set it on the layout params. 139 final int idealDrawerWidth = 5 * actionBarSize; 140 final int maxDrawerWidth = Math.max(0, drawerLayoutWidth - actionBarSize); 141 final int drawerWidth = Math.min(idealDrawerWidth, maxDrawerWidth); 142 143 final DrawerLayout.LayoutParams drawerLp = 144 (DrawerLayout.LayoutParams) mDrawer.getLayoutParams(); 145 drawerLp.width = drawerWidth; 146 mDrawer.setLayoutParams(drawerLp); 147 148 // Remove ourselves as the pre-draw listener since this is a one-time 149 // configuration. 150 mDrawerLayout.getViewTreeObserver().removeOnPreDrawListener(this); 151 return true; 152 } 153 }); 154 } 155 156 @Override 157 protected void onPostCreate(Bundle savedInstanceState) { 158 super.onPostCreate(savedInstanceState); 159 160 // Sync the toggle state after onRestoreInstanceState has occurred. 161 mDrawerToggle.syncState(); 162 } 163 164 @Override 165 public boolean onOptionsItemSelected(MenuItem item) { 166 /* 167 * The action bar home/up action should open or close the drawer. 168 * The drawer toggle will take care of this. 169 */ 170 if (mDrawerToggle.onOptionsItemSelected(item)) { 171 return true; 172 } 173 return super.onOptionsItemSelected(item); 174 } 175 176 @Override 177 public void onBackPressed() { 178 // Is the drawer open? 179 if (mDrawerLayout.isDrawerOpen(mDrawer)) { 180 // Close the drawer and return. 181 mDrawerLayout.closeDrawer(mDrawer); 182 return; 183 } 184 185 super.onBackPressed(); 186 } 187 188 @Override 189 public void onConfigurationChanged(Configuration newConfig) { 190 super.onConfigurationChanged(newConfig); 191 mDrawerToggle.onConfigurationChanged(newConfig); 192 } 193 194 /** 195 * This list item click listener implements very simple view switching by changing 196 * the primary content text. The drawer is closed when a selection is made. 197 */ 198 private class DrawerItemClickListener implements ListView.OnItemClickListener { 199 @Override 200 public void onItemClick(AdapterView<?> parent, View view, int position, long id) { 201 mContent.setText(Shakespeare.DIALOGUE[position]); 202 mToolbar.setTitle(Shakespeare.TITLES[position]); 203 mDrawerLayout.closeDrawer(mDrawer); 204 } 205 } 206} 207