ActionBarActivity.java revision b933f9c89bbe890ff6753559b83c0ecf236472dd
1/* 2 * Copyright (C) 2012 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.app.Activity; 20import android.content.Intent; 21import android.content.res.Configuration; 22import android.os.Build; 23import android.os.Bundle; 24import android.support.annotation.LayoutRes; 25import android.support.v4.app.ActionBarDrawerToggle; 26import android.support.v4.app.ActivityCompat; 27import android.support.v4.app.FragmentActivity; 28import android.support.v4.app.NavUtils; 29import android.support.v4.app.TaskStackBuilder; 30import android.support.v4.view.WindowCompat; 31import android.support.v7.view.ActionMode; 32import android.view.Menu; 33import android.view.MenuInflater; 34import android.view.MenuItem; 35import android.view.View; 36import android.view.ViewGroup; 37import android.view.Window; 38 39/** 40 * Base class for activities that use the <a 41 * href="{@docRoot}tools/extras/support-library.html">support library</a> action bar features. 42 * 43 * <p>You can add an {@link ActionBar} to your activity when running on API level 7 or higher 44 * by extending this class for your activity and setting the activity theme to 45 * {@link android.support.v7.appcompat.R.style#Theme_AppCompat Theme.AppCompat} or a similar theme. 46 * 47 * <div class="special reference"> 48 * <h3>Developer Guides</h3> 49 * 50 * <p>For information about how to use the action bar, including how to add action items, navigation 51 * modes and more, read the <a href="{@docRoot}guide/topics/ui/actionbar.html">Action 52 * Bar</a> API guide.</p> 53 * </div> 54 */ 55public class ActionBarActivity extends FragmentActivity implements ActionBar.Callback, 56 TaskStackBuilder.SupportParentable, ActionBarDrawerToggle.DelegateProvider { 57 ActionBarActivityDelegate mImpl; 58 59 /** 60 * Support library version of {@link Activity#getActionBar}. 61 * 62 * <p>Retrieve a reference to this activity's ActionBar. 63 * 64 * @return The Activity's ActionBar, or null if it does not have one. 65 */ 66 public ActionBar getSupportActionBar() { 67 return mImpl.getSupportActionBar(); 68 } 69 70 @Override 71 public MenuInflater getMenuInflater() { 72 return mImpl.getMenuInflater(); 73 } 74 75 @Override 76 public void setContentView(@LayoutRes int layoutResID) { 77 mImpl.setContentView(layoutResID); 78 } 79 80 @Override 81 public void setContentView(View view) { 82 mImpl.setContentView(view); 83 } 84 85 @Override 86 public void setContentView(View view, ViewGroup.LayoutParams params) { 87 mImpl.setContentView(view, params); 88 } 89 90 @Override 91 public void addContentView(View view, ViewGroup.LayoutParams params) { 92 mImpl.addContentView(view, params); 93 } 94 95 @Override 96 protected void onCreate(Bundle savedInstanceState) { 97 mImpl = ActionBarActivityDelegate.createDelegate(this); 98 super.onCreate(savedInstanceState); 99 mImpl.onCreate(savedInstanceState); 100 } 101 102 @Override 103 public void onConfigurationChanged(Configuration newConfig) { 104 super.onConfigurationChanged(newConfig); 105 mImpl.onConfigurationChanged(newConfig); 106 } 107 108 @Override 109 protected void onStop() { 110 super.onStop(); 111 mImpl.onStop(); 112 } 113 114 @Override 115 protected void onPostResume() { 116 super.onPostResume(); 117 mImpl.onPostResume(); 118 } 119 120 @Override 121 public View onCreatePanelView(int featureId) { 122 if (featureId == Window.FEATURE_OPTIONS_PANEL) { 123 return mImpl.onCreatePanelView(featureId); 124 } else { 125 return super.onCreatePanelView(featureId); 126 } 127 } 128 129 @Override 130 public final boolean onMenuItemSelected(int featureId, android.view.MenuItem item) { 131 if (mImpl.onMenuItemSelected(featureId, item)) { 132 return true; 133 } 134 135 final ActionBar ab = getSupportActionBar(); 136 if (item.getItemId() == android.R.id.home && ab != null && 137 (ab.getDisplayOptions() & ActionBar.DISPLAY_HOME_AS_UP) != 0) { 138 return onSupportNavigateUp(); 139 } 140 return false; 141 } 142 143 @Override 144 protected void onTitleChanged(CharSequence title, int color) { 145 super.onTitleChanged(title, color); 146 mImpl.onTitleChanged(title); 147 } 148 149 /** 150 * Enable extended support library window features. 151 * <p> 152 * This is a convenience for calling 153 * {@link android.view.Window#requestFeature getWindow().requestFeature()}. 154 * </p> 155 * 156 * @param featureId The desired feature as defined in 157 * {@link android.view.Window} or {@link WindowCompat}. 158 * @return Returns true if the requested feature is supported and now enabled. 159 * 160 * @see android.app.Activity#requestWindowFeature 161 * @see android.view.Window#requestFeature 162 */ 163 public boolean supportRequestWindowFeature(int featureId) { 164 return mImpl.supportRequestWindowFeature(featureId); 165 } 166 167 @Override 168 public void supportInvalidateOptionsMenu() { 169 // Only call up to super on ICS+ 170 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH) { 171 super.supportInvalidateOptionsMenu(); 172 } 173 mImpl.supportInvalidateOptionsMenu(); 174 } 175 176 /** 177 * Notifies the Activity that a support action mode has been started. 178 * Activity subclasses overriding this method should call the superclass implementation. 179 * 180 * @param mode The new action mode. 181 */ 182 public void onSupportActionModeStarted(ActionMode mode) { 183 } 184 185 /** 186 * Notifies the activity that a support action mode has finished. 187 * Activity subclasses overriding this method should call the superclass implementation. 188 * 189 * @param mode The action mode that just finished. 190 */ 191 public void onSupportActionModeFinished(ActionMode mode) { 192 } 193 194 public ActionMode startSupportActionMode(ActionMode.Callback callback) { 195 return mImpl.startSupportActionMode(callback); 196 } 197 198 @Override 199 public boolean onCreatePanelMenu(int featureId, Menu menu) { 200 return mImpl.onCreatePanelMenu(featureId, menu); 201 } 202 203 @Override 204 public boolean onPreparePanel(int featureId, View view, Menu menu) { 205 return mImpl.onPreparePanel(featureId, view, menu); 206 } 207 208 /** 209 * @hide 210 */ 211 @Override 212 protected boolean onPrepareOptionsPanel(View view, Menu menu) { 213 return mImpl.onPrepareOptionsPanel(view, menu); 214 } 215 216 void superSetContentView(int resId) { 217 super.setContentView(resId); 218 } 219 220 void superSetContentView(View v) { 221 super.setContentView(v); 222 } 223 224 void superSetContentView(View v, ViewGroup.LayoutParams lp) { 225 super.setContentView(v, lp); 226 } 227 228 void superAddContentView(View v, ViewGroup.LayoutParams lp) { 229 super.addContentView(v, lp); 230 } 231 232 boolean superOnCreatePanelMenu(int featureId, android.view.Menu frameworkMenu) { 233 return super.onCreatePanelMenu(featureId, frameworkMenu); 234 } 235 236 boolean superOnPreparePanel(int featureId, View view, android.view.Menu menu) { 237 return super.onPreparePanel(featureId, view, menu); 238 } 239 240 boolean superOnPrepareOptionsPanel(View view, Menu menu) { 241 return super.onPrepareOptionsPanel(view, menu); 242 } 243 244 boolean superOnMenuItemSelected(int featureId, MenuItem menuItem) { 245 return super.onMenuItemSelected(featureId, menuItem); 246 } 247 248 @Override 249 public void onBackPressed() { 250 if (!mImpl.onBackPressed()) { 251 super.onBackPressed(); 252 } 253 } 254 255 /** 256 * Support library version of {@link Activity#setProgressBarVisibility(boolean)} 257 * <p> 258 * Sets the visibility of the progress bar in the title. 259 * <p> 260 * In order for the progress bar to be shown, the feature must be requested 261 * via {@link #supportRequestWindowFeature(int)}. 262 * 263 * @param visible Whether to show the progress bars in the title. 264 */ 265 public void setSupportProgressBarVisibility(boolean visible) { 266 mImpl.setSupportProgressBarVisibility(visible); 267 } 268 269 /** 270 * Support library version of {@link Activity#setProgressBarIndeterminateVisibility(boolean)} 271 * <p> 272 * Sets the visibility of the indeterminate progress bar in the title. 273 * <p> 274 * In order for the progress bar to be shown, the feature must be requested 275 * via {@link #supportRequestWindowFeature(int)}. 276 * 277 * @param visible Whether to show the progress bars in the title. 278 */ 279 public void setSupportProgressBarIndeterminateVisibility(boolean visible) { 280 mImpl.setSupportProgressBarIndeterminateVisibility(visible); 281 } 282 283 /** 284 * Support library version of {@link Activity#setProgressBarIndeterminate(boolean)} 285 * <p> 286 * Sets whether the horizontal progress bar in the title should be indeterminate (the 287 * circular is always indeterminate). 288 * <p> 289 * In order for the progress bar to be shown, the feature must be requested 290 * via {@link #supportRequestWindowFeature(int)}. 291 * 292 * @param indeterminate Whether the horizontal progress bar should be indeterminate. 293 */ 294 public void setSupportProgressBarIndeterminate(boolean indeterminate) { 295 mImpl.setSupportProgressBarIndeterminate(indeterminate); 296 } 297 298 /** 299 * Support library version of {@link Activity#setProgress(int)}. 300 * <p> 301 * Sets the progress for the progress bars in the title. 302 * <p> 303 * In order for the progress bar to be shown, the feature must be requested 304 * via {@link #supportRequestWindowFeature(int)}. 305 * 306 * @param progress The progress for the progress bar. Valid ranges are from 307 * 0 to 10000 (both inclusive). If 10000 is given, the progress 308 * bar will be completely filled and will fade out. 309 */ 310 public void setSupportProgress(int progress) { 311 mImpl.setSupportProgress(progress); 312 } 313 314 /** 315 * Support version of {@link #onCreateNavigateUpTaskStack(android.app.TaskStackBuilder)}. 316 * This method will be called on all platform versions. 317 * 318 * Define the synthetic task stack that will be generated during Up navigation from 319 * a different task. 320 * 321 * <p>The default implementation of this method adds the parent chain of this activity 322 * as specified in the manifest to the supplied {@link TaskStackBuilder}. Applications 323 * may choose to override this method to construct the desired task stack in a different 324 * way.</p> 325 * 326 * <p>This method will be invoked by the default implementation of {@link #onNavigateUp()} 327 * if {@link #shouldUpRecreateTask(Intent)} returns true when supplied with the intent 328 * returned by {@link #getParentActivityIntent()}.</p> 329 * 330 * <p>Applications that wish to supply extra Intent parameters to the parent stack defined 331 * by the manifest should override 332 * {@link #onPrepareSupportNavigateUpTaskStack(TaskStackBuilder)}.</p> 333 * 334 * @param builder An empty TaskStackBuilder - the application should add intents representing 335 * the desired task stack 336 */ 337 public void onCreateSupportNavigateUpTaskStack(TaskStackBuilder builder) { 338 builder.addParentStack(this); 339 } 340 341 /** 342 * Support version of {@link #onPrepareNavigateUpTaskStack(android.app.TaskStackBuilder)}. 343 * This method will be called on all platform versions. 344 * 345 * Prepare the synthetic task stack that will be generated during Up navigation 346 * from a different task. 347 * 348 * <p>This method receives the {@link TaskStackBuilder} with the constructed series of 349 * Intents as generated by {@link #onCreateSupportNavigateUpTaskStack(TaskStackBuilder)}. 350 * If any extra data should be added to these intents before launching the new task, 351 * the application should override this method and add that data here.</p> 352 * 353 * @param builder A TaskStackBuilder that has been populated with Intents by 354 * onCreateNavigateUpTaskStack. 355 */ 356 public void onPrepareSupportNavigateUpTaskStack(TaskStackBuilder builder) { 357 } 358 359 /** 360 * This method is called whenever the user chooses to navigate Up within your application's 361 * activity hierarchy from the action bar. 362 * 363 * <p>If a parent was specified in the manifest for this activity or an activity-alias to it, 364 * default Up navigation will be handled automatically. See 365 * {@link #getSupportParentActivityIntent()} for how to specify the parent. If any activity 366 * along the parent chain requires extra Intent arguments, the Activity subclass 367 * should override the method {@link #onPrepareSupportNavigateUpTaskStack(TaskStackBuilder)} 368 * to supply those arguments.</p> 369 * 370 * <p>See <a href="{@docRoot}guide/topics/fundamentals/tasks-and-back-stack.html">Tasks and 371 * Back Stack</a> from the developer guide and 372 * <a href="{@docRoot}design/patterns/navigation.html">Navigation</a> from the design guide 373 * for more information about navigating within your app.</p> 374 * 375 * <p>See the {@link TaskStackBuilder} class and the Activity methods 376 * {@link #getSupportParentActivityIntent()}, {@link #supportShouldUpRecreateTask(Intent)}, and 377 * {@link #supportNavigateUpTo(Intent)} for help implementing custom Up navigation.</p> 378 * 379 * @return true if Up navigation completed successfully and this Activity was finished, 380 * false otherwise. 381 */ 382 public boolean onSupportNavigateUp() { 383 Intent upIntent = getSupportParentActivityIntent(); 384 385 if (upIntent != null) { 386 if (supportShouldUpRecreateTask(upIntent)) { 387 TaskStackBuilder b = TaskStackBuilder.create(this); 388 onCreateSupportNavigateUpTaskStack(b); 389 onPrepareSupportNavigateUpTaskStack(b); 390 b.startActivities(); 391 392 try { 393 ActivityCompat.finishAffinity(this); 394 } catch (IllegalStateException e) { 395 // This can only happen on 4.1+, when we don't have a parent or a result set. 396 // In that case we should just finish(). 397 finish(); 398 } 399 } else { 400 // This activity is part of the application's task, so simply 401 // navigate up to the hierarchical parent activity. 402 supportNavigateUpTo(upIntent); 403 } 404 return true; 405 } 406 return false; 407 } 408 409 /** 410 * Obtain an {@link Intent} that will launch an explicit target activity 411 * specified by sourceActivity's {@link NavUtils#PARENT_ACTIVITY} <meta-data> 412 * element in the application's manifest. If the device is running 413 * Jellybean or newer, the android:parentActivityName attribute will be preferred 414 * if it is present. 415 * 416 * @return a new Intent targeting the defined parent activity of sourceActivity 417 */ 418 public Intent getSupportParentActivityIntent() { 419 return NavUtils.getParentActivityIntent(this); 420 } 421 422 /** 423 * Returns true if sourceActivity should recreate the task when navigating 'up' 424 * by using targetIntent. 425 * 426 * <p>If this method returns false the app can trivially call 427 * {@link #supportNavigateUpTo(Intent)} using the same parameters to correctly perform 428 * up navigation. If this method returns false, the app should synthesize a new task stack 429 * by using {@link TaskStackBuilder} or another similar mechanism to perform up navigation.</p> 430 * 431 * @param targetIntent An intent representing the target destination for up navigation 432 * @return true if navigating up should recreate a new task stack, false if the same task 433 * should be used for the destination 434 */ 435 public boolean supportShouldUpRecreateTask(Intent targetIntent) { 436 return NavUtils.shouldUpRecreateTask(this, targetIntent); 437 } 438 439 /** 440 * Navigate from sourceActivity to the activity specified by upIntent, finishing sourceActivity 441 * in the process. upIntent will have the flag {@link Intent#FLAG_ACTIVITY_CLEAR_TOP} set 442 * by this method, along with any others required for proper up navigation as outlined 443 * in the Android Design Guide. 444 * 445 * <p>This method should be used when performing up navigation from within the same task 446 * as the destination. If up navigation should cross tasks in some cases, see 447 * {@link #supportShouldUpRecreateTask(Intent)}.</p> 448 * 449 * @param upIntent An intent representing the target destination for up navigation 450 */ 451 public void supportNavigateUpTo(Intent upIntent) { 452 NavUtils.navigateUpTo(this, upIntent); 453 } 454 455 @Override 456 public final ActionBarDrawerToggle.Delegate getDrawerToggleDelegate() { 457 return mImpl.getDrawerToggleDelegate(); 458 } 459 460 /** 461 * Use {@link #onSupportContentChanged()} instead. 462 */ 463 public final void onContentChanged() { 464 mImpl.onContentChanged(); 465 } 466 467 /** 468 * This hook is called whenever the content view of the screen changes. 469 * @see android.app.Activity#onContentChanged() 470 */ 471 public void onSupportContentChanged() { 472 } 473} 474