| /* |
| * Copyright (C) 2015 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.supportv7.widget; |
| |
| import android.content.res.Configuration; |
| import android.content.res.Resources; |
| import android.content.res.TypedArray; |
| import android.os.Bundle; |
| import android.support.v4.content.ContextCompat; |
| import android.support.v4.view.GravityCompat; |
| import android.support.v4.widget.DrawerLayout; |
| import android.support.v7.app.ActionBarDrawerToggle; |
| import android.support.v7.app.AppCompatActivity; |
| import android.support.v7.widget.Toolbar; |
| import android.view.MenuItem; |
| import android.view.View; |
| import android.view.ViewTreeObserver; |
| import android.widget.AdapterView; |
| import android.widget.ArrayAdapter; |
| import android.widget.FrameLayout; |
| import android.widget.ListView; |
| import android.widget.TextView; |
| import com.example.android.supportv7.R; |
| import com.example.android.supportv7.Shakespeare; |
| |
| /** |
| * This example illustrates a common usage of the DrawerLayout widget combined with Toolbar |
| * in the Android support library that respect the |
| * <a href="https://www.google.com/design/spec/patterns/navigation-drawer.html">Material design |
| * guidelines</a> for the drawer component. |
| * |
| * |
| * <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> |
| * |
| * <p>When the drawer is open, it is above the application toolbar. On Lollipop versions of the |
| * platform and above the drawer spans the full height of the screen, including behind the system |
| * status bar.</p> |
| */ |
| public class DrawerLayoutActivity extends AppCompatActivity { |
| private DrawerLayout mDrawerLayout; |
| private ListView mStartDrawer; |
| private FrameLayout mEndDrawer; |
| private TextView mContent; |
| |
| private ActionBarDrawerToggle mDrawerToggle; |
| private Toolbar mToolbar; |
| |
| @Override |
| protected void onCreate(Bundle savedInstanceState) { |
| super.onCreate(savedInstanceState); |
| |
| setContentView(R.layout.drawer_layout); |
| |
| mDrawerLayout = (DrawerLayout) findViewById(R.id.drawer_layout); |
| mStartDrawer = (ListView) findViewById(R.id.start_drawer); |
| mEndDrawer = (FrameLayout) findViewById(R.id.end_drawer); |
| mContent = (TextView) findViewById(R.id.content_text); |
| |
| mDrawerLayout.setDrawerShadow(R.drawable.drawer_shadow, GravityCompat.START); |
| mDrawerLayout.setDrawerShadow(R.drawable.drawer_shadow_end, GravityCompat.END); |
| |
| // 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)); |
| |
| mStartDrawer.setAdapter(new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, |
| Shakespeare.TITLES)); |
| mStartDrawer.setOnItemClickListener(new DrawerItemClickListener()); |
| |
| // Find the toolbar in our layout and set it as the support action bar on the activity. |
| // This is required to have the drawer slide "over" the toolbar. |
| mToolbar = (Toolbar) findViewById(R.id.toolbar); |
| mToolbar.setTitle(R.string.drawer_title); |
| setSupportActionBar(mToolbar); |
| |
| getSupportActionBar().setDisplayHomeAsUpEnabled(true); |
| getSupportActionBar().setDisplayShowHomeEnabled(false); |
| |
| // ActionBarDrawerToggle provides convenient helpers for tying together the |
| // prescribed interactions between a top-level sliding drawer and the action bar. |
| // Note that, as the Javadocs of ActionBarDrawerToggle constructors say, we are |
| // *not* using a constructor that gets a Toolbar since we're setting our toolbar |
| // dynamically at runtime. Furthermore, as the drawer is sliding over the toolbar, |
| // we are suppressing the morphing animation from hamburger to back arrow by |
| // calling super.onDrawerSlide with slideOffset=0.0f. In case your app only has |
| // top-level pages and doesn't need back arrow visuals at all, you can set up |
| // your activity theme to have attribute named "drawerArrowStyle" that points |
| // to an extension of Widget.AppCompat.DrawerArrowToggle that has its "spinBars" |
| // attribute set to false. |
| mDrawerToggle = new ActionBarDrawerToggle(this, mDrawerLayout, |
| R.string.drawer_open, R.string.drawer_close) { |
| @Override |
| public void onDrawerOpened(View drawerView) { |
| super.onDrawerOpened(drawerView); |
| super.onDrawerSlide(drawerView, 0.0f); |
| } |
| |
| @Override |
| public void onDrawerSlide(View drawerView, float slideOffset) { |
| super.onDrawerSlide(drawerView, 0.0f); |
| } |
| }; |
| |
| mDrawerLayout.addDrawerListener(mDrawerToggle); |
| |
| // Configure the background color fill of the system status bar (on supported platform |
| // versions) and the toolbar itself. We're using the same color, and android:statusBar |
| // from the theme makes the status bar slightly darker. |
| final int metalBlueColor = ContextCompat.getColor(this, R.color.drawer_sample_metal_blue); |
| mDrawerLayout.setStatusBarBackgroundColor(metalBlueColor); |
| mToolbar.setBackgroundColor(metalBlueColor); |
| |
| // Register a pre-draw listener to get the initial width of the DrawerLayout so |
| // that we can determine the width of the drawer based on the Material spec at |
| // https://www.google.com/design/spec/patterns/navigation-drawer.html#navigation-drawer-specs |
| mDrawerLayout.getViewTreeObserver().addOnPreDrawListener( |
| new ViewTreeObserver.OnPreDrawListener() { |
| @Override |
| public boolean onPreDraw() { |
| // What is the width of the entire DrawerLayout? |
| final int drawerLayoutWidth = mDrawerLayout.getWidth(); |
| |
| // What is the action bar size? |
| final Resources.Theme theme = mDrawerLayout.getContext().getTheme(); |
| final TypedArray a = theme.obtainStyledAttributes( |
| new int[] { android.support.v7.appcompat.R.attr.actionBarSize }); |
| final int actionBarSize = a.getDimensionPixelSize(0, 0); |
| if (a != null) { |
| a.recycle(); |
| } |
| |
| // Compute the width of the drawer and set it on the layout params. |
| final int idealDrawerWidth = 5 * actionBarSize; |
| final int maxDrawerWidth = Math.max(0, drawerLayoutWidth - actionBarSize); |
| final int drawerWidth = Math.min(idealDrawerWidth, maxDrawerWidth); |
| |
| final DrawerLayout.LayoutParams startDrawerLp = |
| (DrawerLayout.LayoutParams) mStartDrawer.getLayoutParams(); |
| startDrawerLp.width = drawerWidth; |
| mStartDrawer.setLayoutParams(startDrawerLp); |
| |
| final DrawerLayout.LayoutParams endDrawerLp = |
| (DrawerLayout.LayoutParams) mEndDrawer.getLayoutParams(); |
| endDrawerLp.width = drawerWidth; |
| mEndDrawer.setLayoutParams(endDrawerLp); |
| |
| // Remove ourselves as the pre-draw listener since this is a one-time |
| // configuration. |
| mDrawerLayout.getViewTreeObserver().removeOnPreDrawListener(this); |
| return true; |
| } |
| }); |
| } |
| |
| @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. |
| * The drawer toggle will take care of this. |
| */ |
| if (mDrawerToggle.onOptionsItemSelected(item)) { |
| return true; |
| } |
| return super.onOptionsItemSelected(item); |
| } |
| |
| @Override |
| public void onBackPressed() { |
| boolean hadOpenDrawer = false; |
| // Is the start drawer open? |
| if (mDrawerLayout.isDrawerOpen(mStartDrawer)) { |
| // Close it |
| mDrawerLayout.closeDrawer(mStartDrawer); |
| hadOpenDrawer = true; |
| } |
| // Is the end drawer open? |
| if (mDrawerLayout.isDrawerOpen(mEndDrawer)) { |
| // Close it |
| mDrawerLayout.closeDrawer(mEndDrawer); |
| hadOpenDrawer = true; |
| } |
| |
| if (hadOpenDrawer) { |
| // If we had one or both drawers open, now that we've closed it / them, return. |
| return; |
| } |
| |
| super.onBackPressed(); |
| } |
| |
| @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]); |
| mToolbar.setTitle(Shakespeare.TITLES[position]); |
| mDrawerLayout.closeDrawer(mStartDrawer); |
| } |
| } |
| } |