• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2014 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 package com.example.android.navigationdrawer;
18 
19 import android.app.Activity;
20 import android.app.Fragment;
21 import android.app.FragmentManager;
22 import android.app.FragmentTransaction;
23 import android.app.SearchManager;
24 import android.content.Intent;
25 import android.content.res.Configuration;
26 import android.os.Bundle;
27 import android.support.v4.app.ActionBarDrawerToggle;
28 import android.support.v4.view.GravityCompat;
29 import android.support.v4.widget.DrawerLayout;
30 import android.support.v7.widget.LinearLayoutManager;
31 import android.support.v7.widget.RecyclerView;
32 import android.view.LayoutInflater;
33 import android.view.Menu;
34 import android.view.MenuItem;
35 import android.view.View;
36 import android.view.ViewGroup;
37 import android.widget.ImageView;
38 import android.widget.Toast;
39 
40 import java.util.Locale;
41 
42 /**
43  * This example illustrates a common usage of the DrawerLayout widget
44  * in the Android support library.
45  * <p/>
46  * <p>When a navigation (left) drawer is present, the host activity should detect presses of
47  * the action bar's Up affordance as a signal to open and close the navigation drawer. The
48  * ActionBarDrawerToggle facilitates this behavior.
49  * Items within the drawer should fall into one of two categories:</p>
50  * <p/>
51  * <ul>
52  * <li><strong>View switches</strong>. A view switch follows the same basic policies as
53  * list or tab navigation in that a view switch does not create navigation history.
54  * This pattern should only be used at the root activity of a task, leaving some form
55  * of Up navigation active for activities further down the navigation hierarchy.</li>
56  * <li><strong>Selective Up</strong>. The drawer allows the user to choose an alternate
57  * parent for Up navigation. This allows a user to jump across an app's navigation
58  * hierarchy at will. The application should treat this as it treats Up navigation from
59  * a different task, replacing the current task stack using TaskStackBuilder or similar.
60  * This is the only form of navigation drawer that should be used outside of the root
61  * activity of a task.</li>
62  * </ul>
63  * <p/>
64  * <p>Right side drawers should be used for actions, not navigation. This follows the pattern
65  * established by the Action Bar that navigation should be to the left and actions to the right.
66  * An action should be an operation performed on the current contents of the window,
67  * for example enabling or disabling a data overlay on top of the current content.</p>
68  */
69 public class NavigationDrawerActivity extends Activity implements PlanetAdapter.OnItemClickListener {
70     private DrawerLayout mDrawerLayout;
71     private RecyclerView mDrawerList;
72     private ActionBarDrawerToggle mDrawerToggle;
73 
74     private CharSequence mDrawerTitle;
75     private CharSequence mTitle;
76     private String[] mPlanetTitles;
77 
78     @Override
onCreate(Bundle savedInstanceState)79     protected void onCreate(Bundle savedInstanceState) {
80         super.onCreate(savedInstanceState);
81         setContentView(R.layout.activity_navigation_drawer);
82 
83         mTitle = mDrawerTitle = getTitle();
84         mPlanetTitles = getResources().getStringArray(R.array.planets_array);
85         mDrawerLayout = (DrawerLayout) findViewById(R.id.drawer_layout);
86         mDrawerList = (RecyclerView) findViewById(R.id.left_drawer);
87 
88         // set a custom shadow that overlays the main content when the drawer opens
89         mDrawerLayout.setDrawerShadow(R.drawable.drawer_shadow, GravityCompat.START);
90         // improve performance by indicating the list if fixed size.
91         mDrawerList.setHasFixedSize(true);
92         mDrawerList.setLayoutManager(new LinearLayoutManager(this));
93 
94         // set up the drawer's list view with items and click listener
95         mDrawerList.setAdapter(new PlanetAdapter(mPlanetTitles, this));
96         // enable ActionBar app icon to behave as action to toggle nav drawer
97         getActionBar().setDisplayHomeAsUpEnabled(true);
98         getActionBar().setHomeButtonEnabled(true);
99 
100         // ActionBarDrawerToggle ties together the the proper interactions
101         // between the sliding drawer and the action bar app icon
102         mDrawerToggle = new ActionBarDrawerToggle(
103                 this,                  /* host Activity */
104                 mDrawerLayout,         /* DrawerLayout object */
105                 R.drawable.ic_drawer,  /* nav drawer image to replace 'Up' caret */
106                 R.string.drawer_open,  /* "open drawer" description for accessibility */
107                 R.string.drawer_close  /* "close drawer" description for accessibility */
108         ) {
109             public void onDrawerClosed(View view) {
110                 getActionBar().setTitle(mTitle);
111                 invalidateOptionsMenu(); // creates call to onPrepareOptionsMenu()
112             }
113 
114             public void onDrawerOpened(View drawerView) {
115                 getActionBar().setTitle(mDrawerTitle);
116                 invalidateOptionsMenu(); // creates call to onPrepareOptionsMenu()
117             }
118         };
119         mDrawerLayout.setDrawerListener(mDrawerToggle);
120 
121         if (savedInstanceState == null) {
122             selectItem(0);
123         }
124     }
125 
126 
127     @Override
onCreateOptionsMenu(Menu menu)128     public boolean onCreateOptionsMenu(Menu menu) {
129         // Inflate the menu; this adds items to the action bar if it is present.
130         getMenuInflater().inflate(R.menu.navigation_drawer, menu);
131         return true;
132     }
133 
134     /* Called whenever we call invalidateOptionsMenu() */
135     @Override
onPrepareOptionsMenu(Menu menu)136     public boolean onPrepareOptionsMenu(Menu menu) {
137         // If the nav drawer is open, hide action items related to the content view
138         boolean drawerOpen = mDrawerLayout.isDrawerOpen(mDrawerList);
139         menu.findItem(R.id.action_websearch).setVisible(!drawerOpen);
140         return super.onPrepareOptionsMenu(menu);
141     }
142 
143     @Override
onOptionsItemSelected(MenuItem item)144     public boolean onOptionsItemSelected(MenuItem item) {
145         // The action bar home/up action should open or close the drawer.
146         // ActionBarDrawerToggle will take care of this.
147         if (mDrawerToggle.onOptionsItemSelected(item)) {
148             return true;
149         }
150         // Handle action buttons
151         switch (item.getItemId()) {
152             case R.id.action_websearch:
153                 // create intent to perform web search for this planet
154                 Intent intent = new Intent(Intent.ACTION_WEB_SEARCH);
155                 intent.putExtra(SearchManager.QUERY, getActionBar().getTitle());
156                 // catch event that there's no activity to handle intent
157                 if (intent.resolveActivity(getPackageManager()) != null) {
158                     startActivity(intent);
159                 } else {
160                     Toast.makeText(this, R.string.app_not_available, Toast.LENGTH_LONG).show();
161                 }
162                 return true;
163             default:
164                 return super.onOptionsItemSelected(item);
165         }
166     }
167 
168     /* The click listener for RecyclerView in the navigation drawer */
169     @Override
onClick(View view, int position)170     public void onClick(View view, int position) {
171         selectItem(position);
172     }
173 
selectItem(int position)174     private void selectItem(int position) {
175         // update the main content by replacing fragments
176         Fragment fragment = PlanetFragment.newInstance(position);
177 
178         FragmentManager fragmentManager = getFragmentManager();
179         FragmentTransaction ft = fragmentManager.beginTransaction();
180         ft.replace(R.id.content_frame, fragment);
181         ft.commit();
182 
183         // update selected item title, then close the drawer
184         setTitle(mPlanetTitles[position]);
185         mDrawerLayout.closeDrawer(mDrawerList);
186     }
187 
188     @Override
setTitle(CharSequence title)189     public void setTitle(CharSequence title) {
190         mTitle = title;
191         getActionBar().setTitle(mTitle);
192     }
193 
194     /**
195      * When using the ActionBarDrawerToggle, you must call it during
196      * onPostCreate() and onConfigurationChanged()...
197      */
198 
199     @Override
onPostCreate(Bundle savedInstanceState)200     protected void onPostCreate(Bundle savedInstanceState) {
201         super.onPostCreate(savedInstanceState);
202         // Sync the toggle state after onRestoreInstanceState has occurred.
203         mDrawerToggle.syncState();
204     }
205 
206     @Override
onConfigurationChanged(Configuration newConfig)207     public void onConfigurationChanged(Configuration newConfig) {
208         super.onConfigurationChanged(newConfig);
209         // Pass any configuration change to the drawer toggls
210         mDrawerToggle.onConfigurationChanged(newConfig);
211     }
212 
213     /**
214      * Fragment that appears in the "content_frame", shows a planet
215      */
216     public static class PlanetFragment extends Fragment {
217         public static final String ARG_PLANET_NUMBER = "planet_number";
218 
PlanetFragment()219         public PlanetFragment() {
220             // Empty constructor required for fragment subclasses
221         }
222 
newInstance(int position)223         public static Fragment newInstance(int position) {
224             Fragment fragment = new PlanetFragment();
225             Bundle args = new Bundle();
226             args.putInt(PlanetFragment.ARG_PLANET_NUMBER, position);
227             fragment.setArguments(args);
228             return fragment;
229         }
230 
231         @Override
onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)232         public View onCreateView(LayoutInflater inflater, ViewGroup container,
233                                  Bundle savedInstanceState) {
234             View rootView = inflater.inflate(R.layout.fragment_planet, container, false);
235             int i = getArguments().getInt(ARG_PLANET_NUMBER);
236             String planet = getResources().getStringArray(R.array.planets_array)[i];
237 
238             int imageId = getResources().getIdentifier(planet.toLowerCase(Locale.getDefault()),
239                     "drawable", getActivity().getPackageName());
240             ImageView iv = ((ImageView) rootView.findViewById(R.id.image));
241             iv.setImageResource(imageId);
242 
243             getActivity().setTitle(planet);
244             return rootView;
245         }
246     }
247 }
248