ActionBarActivityDelegateBase.java revision 4c2a95906254748cb9a843b061288265d6e185a9
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 17package android.support.v7.app; 18 19import android.content.Context; 20import android.content.res.Configuration; 21import android.content.res.Resources; 22import android.content.res.TypedArray; 23import android.os.Bundle; 24import android.support.v4.app.NavUtils; 25import android.support.v4.view.ViewConfigurationCompat; 26import android.support.v4.view.WindowCompat; 27import android.support.v7.appcompat.R; 28import android.support.v7.internal.app.ToolbarActionBar; 29import android.support.v7.internal.app.WindowDecorActionBar; 30import android.support.v7.internal.view.StandaloneActionMode; 31import android.support.v7.internal.view.menu.ListMenuPresenter; 32import android.support.v7.internal.view.menu.MenuBuilder; 33import android.support.v7.internal.view.menu.MenuPresenter; 34import android.support.v7.internal.view.menu.MenuView; 35import android.support.v7.internal.widget.ActionBarContextView; 36import android.support.v7.internal.widget.DecorContentParent; 37import android.support.v7.internal.widget.ProgressBarCompat; 38import android.support.v7.view.ActionMode; 39import android.support.v7.widget.Toolbar; 40import android.util.DisplayMetrics; 41import android.util.TypedValue; 42import android.view.ContextThemeWrapper; 43import android.view.LayoutInflater; 44import android.view.Gravity; 45import android.view.Menu; 46import android.view.MenuItem; 47import android.view.View; 48import android.view.ViewConfiguration; 49import android.view.ViewGroup; 50import android.view.ViewStub; 51import android.view.Window; 52import android.view.accessibility.AccessibilityEvent; 53import android.widget.FrameLayout; 54import android.widget.PopupWindow; 55 56class ActionBarActivityDelegateBase extends ActionBarActivityDelegate implements 57 MenuPresenter.Callback, MenuBuilder.Callback { 58 private static final String TAG = "ActionBarActivityDelegateBase"; 59 60 private static final int[] ACTION_BAR_DRAWABLE_TOGGLE_ATTRS = new int[] { 61 R.attr.homeAsUpIndicator 62 }; 63 64 private DecorContentParent mDecorContentParent; 65 private ListMenuPresenter mListMenuPresenter; 66 private MenuBuilder mMenu; 67 68 ActionMode mActionMode; 69 ActionBarContextView mActionModeView; 70 PopupWindow mActionModePopup; 71 Runnable mShowActionModePopup; 72 73 // true if we have installed a window sub-decor layout. 74 private boolean mSubDecorInstalled; 75 76 private CharSequence mTitleToSet; 77 78 // Used to keep track of Progress Bar Window features 79 private boolean mFeatureProgress, mFeatureIndeterminateProgress; 80 81 // Used for emulating PanelFeatureState 82 private boolean mClosingActionMenu; 83 private boolean mPanelIsPrepared; 84 private boolean mPanelRefreshContent; 85 private Bundle mPanelFrozenActionViewState; 86 87 private boolean mEnableDefaultActionBarUp; 88 89 ActionBarActivityDelegateBase(ActionBarActivity activity) { 90 super(activity); 91 } 92 93 @Override 94 void onCreate(Bundle savedInstanceState) { 95 super.onCreate(savedInstanceState); 96 97 if (NavUtils.getParentActivityName(mActivity) != null) { 98 ActionBar ab = getSupportActionBar(); 99 if (ab == null) { 100 mEnableDefaultActionBarUp = true; 101 } else { 102 ab.setDefaultDisplayHomeAsUpEnabled(true); 103 } 104 } 105 } 106 107 @Override 108 public ActionBar createSupportActionBar() { 109 ensureSubDecor(); 110 ActionBar ab = new WindowDecorActionBar(mActivity, mOverlayActionBar); 111 ab.setDefaultDisplayHomeAsUpEnabled(mEnableDefaultActionBarUp); 112 return ab; 113 } 114 115 @Override 116 void setSupportActionBar(Toolbar toolbar) { 117 if (getSupportActionBar() instanceof WindowDecorActionBar) { 118 throw new IllegalStateException("This Activity already has an action bar supplied " + 119 "by the window decor. Do not request Window.FEATURE_ACTION_BAR and set " + 120 "windowActionBar to false in your theme to use a Toolbar instead."); 121 } 122 ActionBar ab = new ToolbarActionBar(toolbar, mActivity.getTitle(), mWindowMenuCallback); 123 ab.invalidateOptionsMenu(); 124 setSupportActionBar(ab); 125 } 126 127 @Override 128 public void onConfigurationChanged(Configuration newConfig) { 129 // If this is called before sub-decor is installed, ActionBar will not 130 // be properly initialized. 131 if (mHasActionBar && mSubDecorInstalled) { 132 // Note: The action bar will need to access 133 // view changes from superclass. 134 ActionBar ab = getSupportActionBar(); 135 if (ab != null) { 136 ab.onConfigurationChanged(newConfig); 137 } 138 } 139 } 140 141 @Override 142 public void onStop() { 143 ActionBar ab = getSupportActionBar(); 144 if (ab != null) { 145 ab.setShowHideAnimationEnabled(false); 146 } 147 } 148 149 @Override 150 public void onPostResume() { 151 ActionBar ab = getSupportActionBar(); 152 if (ab != null) { 153 ab.setShowHideAnimationEnabled(true); 154 } 155 } 156 157 @Override 158 public void setContentView(View v) { 159 ensureSubDecor(); 160 ViewGroup contentParent = (ViewGroup) mActivity.findViewById(android.R.id.content); 161 contentParent.removeAllViews(); 162 contentParent.addView(v); 163 mActivity.onSupportContentChanged(); 164 } 165 166 @Override 167 public void setContentView(int resId) { 168 ensureSubDecor(); 169 ViewGroup contentParent = (ViewGroup) mActivity.findViewById(android.R.id.content); 170 contentParent.removeAllViews(); 171 mActivity.getLayoutInflater().inflate(resId, contentParent); 172 mActivity.onSupportContentChanged(); 173 } 174 175 @Override 176 public void setContentView(View v, ViewGroup.LayoutParams lp) { 177 ensureSubDecor(); 178 ViewGroup contentParent = (ViewGroup) mActivity.findViewById(android.R.id.content); 179 contentParent.removeAllViews(); 180 contentParent.addView(v, lp); 181 mActivity.onSupportContentChanged(); 182 } 183 184 @Override 185 public void addContentView(View v, ViewGroup.LayoutParams lp) { 186 ensureSubDecor(); 187 ViewGroup contentParent = (ViewGroup) mActivity.findViewById(android.R.id.content); 188 contentParent.addView(v, lp); 189 mActivity.onSupportContentChanged(); 190 } 191 192 @Override 193 public void onContentChanged() { 194 // Ignore all calls to this method as we call onSupportContentChanged manually above 195 } 196 197 final void ensureSubDecor() { 198 if (!mSubDecorInstalled) { 199 if (mHasActionBar) { 200 mActivity.superSetContentView(R.layout.abc_screen_toolbar); 201 202 ViewGroup root = (ViewGroup) mActivity.findViewById(R.id.action_bar_root); 203 if (root != null && root.getChildCount() == 0) { 204 /** 205 * This needs some explanation. As we can not use the android:theme attribute 206 * pre-L, we emulate it by manually creating a LayoutInflater using a 207 * ContextThemeWrapper pointing to actionBarTheme. 208 */ 209 TypedValue outValue = new TypedValue(); 210 mActivity.getTheme().resolveAttribute(R.attr.actionBarTheme, outValue, true); 211 212 Context themedContext; 213 if (outValue.resourceId != 0) { 214 themedContext = new ContextThemeWrapper(mActivity, outValue.resourceId); 215 } else { 216 themedContext = mActivity; 217 } 218 219 LayoutInflater.from(themedContext) 220 .inflate(R.layout.abc_screen_toolbar_include, root, true); 221 } 222 223 mDecorContentParent = (DecorContentParent) mActivity.findViewById(R.id.decor_content_parent); 224 mDecorContentParent.setWindowCallback(mWindowMenuCallback); 225 226 /** 227 * Propagate features to DecorContentParent 228 */ 229 if (mOverlayActionBar) { 230 mDecorContentParent.initFeature(WindowCompat.FEATURE_ACTION_BAR_OVERLAY); 231 } 232 if (mFeatureProgress) { 233 mDecorContentParent.initFeature(Window.FEATURE_PROGRESS); 234 } 235 if (mFeatureIndeterminateProgress) { 236 mDecorContentParent.initFeature(Window.FEATURE_INDETERMINATE_PROGRESS); 237 } 238 } else { 239 mActivity.superSetContentView(R.layout.abc_screen_simple); 240 } 241 242 // Change our content FrameLayout to use the android.R.id.content id. 243 // Useful for fragments. 244 View content = mActivity.findViewById(android.R.id.content); 245 content.setId(View.NO_ID); 246 View abcContent = mActivity.findViewById(R.id.action_bar_activity_content); 247 abcContent.setId(android.R.id.content); 248 249 // A title was set before we've install the decor so set it now. 250 if (mTitleToSet != null && mDecorContentParent != null) { 251 mDecorContentParent.setWindowTitle(mTitleToSet); 252 mTitleToSet = null; 253 } 254 255 applyFixedSizeWindow(); 256 257 onSubDecorInstalled(); 258 259 mSubDecorInstalled = true; 260 261 // Post supportInvalidateOptionsMenu() so that the menu is invalidated post-onCreate() 262 mActivity.getWindow().getDecorView().post(new Runnable() { 263 @Override 264 public void run() { 265 supportInvalidateOptionsMenu(); 266 } 267 }); 268 } 269 } 270 271 void onSubDecorInstalled() {} 272 273 private void applyFixedSizeWindow() { 274 TypedArray a = mActivity.obtainStyledAttributes(R.styleable.Theme); 275 276 TypedValue mFixedWidthMajor = null; 277 TypedValue mFixedWidthMinor = null; 278 TypedValue mFixedHeightMajor = null; 279 TypedValue mFixedHeightMinor = null; 280 281 if (a.hasValue(R.styleable.Theme_windowFixedWidthMajor)) { 282 if (mFixedWidthMajor == null) mFixedWidthMajor = new TypedValue(); 283 a.getValue(R.styleable.Theme_windowFixedWidthMajor, mFixedWidthMajor); 284 } 285 if (a.hasValue(R.styleable.Theme_windowFixedWidthMinor)) { 286 if (mFixedWidthMinor == null) mFixedWidthMinor = new TypedValue(); 287 a.getValue(R.styleable.Theme_windowFixedWidthMinor, mFixedWidthMinor); 288 } 289 if (a.hasValue(R.styleable.Theme_windowFixedHeightMajor)) { 290 if (mFixedHeightMajor == null) mFixedHeightMajor = new TypedValue(); 291 a.getValue(R.styleable.Theme_windowFixedHeightMajor, mFixedHeightMajor); 292 } 293 if (a.hasValue(R.styleable.Theme_windowFixedHeightMinor)) { 294 if (mFixedHeightMinor == null) mFixedHeightMinor = new TypedValue(); 295 a.getValue(R.styleable.Theme_windowFixedHeightMinor, mFixedHeightMinor); 296 } 297 298 final DisplayMetrics metrics = mActivity.getResources().getDisplayMetrics(); 299 final boolean isPortrait = metrics.widthPixels < metrics.heightPixels; 300 int w = ViewGroup.LayoutParams.MATCH_PARENT; 301 int h = ViewGroup.LayoutParams.MATCH_PARENT; 302 303 final TypedValue tvw = isPortrait ? mFixedWidthMinor : mFixedWidthMajor; 304 if (tvw != null && tvw.type != TypedValue.TYPE_NULL) { 305 if (tvw.type == TypedValue.TYPE_DIMENSION) { 306 w = (int) tvw.getDimension(metrics); 307 } else if (tvw.type == TypedValue.TYPE_FRACTION) { 308 w = (int) tvw.getFraction(metrics.widthPixels, metrics.widthPixels); 309 } 310 } 311 312 final TypedValue tvh = isPortrait ? mFixedHeightMajor : mFixedHeightMinor; 313 if (tvh != null && tvh.type != TypedValue.TYPE_NULL) { 314 if (tvh.type == TypedValue.TYPE_DIMENSION) { 315 h = (int) tvh.getDimension(metrics); 316 } else if (tvh.type == TypedValue.TYPE_FRACTION) { 317 h = (int) tvh.getFraction(metrics.heightPixels, metrics.heightPixels); 318 } 319 } 320 321 if (w != ViewGroup.LayoutParams.MATCH_PARENT || h != ViewGroup.LayoutParams.MATCH_PARENT) { 322 mActivity.getWindow().setLayout(w, h); 323 } 324 325 a.recycle(); 326 } 327 328 @Override 329 public boolean supportRequestWindowFeature(int featureId) { 330 switch (featureId) { 331 case WindowCompat.FEATURE_ACTION_BAR: 332 mHasActionBar = true; 333 return true; 334 case WindowCompat.FEATURE_ACTION_BAR_OVERLAY: 335 mOverlayActionBar = true; 336 return true; 337 case Window.FEATURE_PROGRESS: 338 mFeatureProgress = true; 339 return true; 340 case Window.FEATURE_INDETERMINATE_PROGRESS: 341 mFeatureIndeterminateProgress = true; 342 return true; 343 default: 344 return mActivity.requestWindowFeature(featureId); 345 } 346 } 347 348 @Override 349 public void onTitleChanged(CharSequence title) { 350 if (mDecorContentParent != null) { 351 mDecorContentParent.setWindowTitle(title); 352 } else if (getSupportActionBar() != null) { 353 getSupportActionBar().setTitle(title); 354 } else { 355 mTitleToSet = title; 356 } 357 } 358 359 @Override 360 public View onCreatePanelView(int featureId) { 361 View createdPanelView = null; 362 363 if (featureId == Window.FEATURE_OPTIONS_PANEL && preparePanel()) { 364 createdPanelView = (View) getListMenuView(mActivity, this); 365 } 366 367 return createdPanelView; 368 } 369 370 @Override 371 public boolean onCreatePanelMenu(int featureId, Menu menu) { 372 if (featureId != Window.FEATURE_OPTIONS_PANEL) { 373 return mActivity.superOnCreatePanelMenu(featureId, menu); 374 } 375 return false; 376 } 377 378 @Override 379 public boolean onPreparePanel(int featureId, View view, Menu menu) { 380 if (featureId != Window.FEATURE_OPTIONS_PANEL) { 381 return mActivity.superOnPreparePanel(featureId, view, menu); 382 } 383 return false; 384 } 385 386 @Override 387 public boolean onMenuItemSelected(MenuBuilder menu, MenuItem item) { 388 return mActivity.onMenuItemSelected(Window.FEATURE_OPTIONS_PANEL, item); 389 } 390 391 @Override 392 public void onMenuModeChange(MenuBuilder menu) { 393 reopenMenu(menu, true); 394 } 395 396 @Override 397 public void onCloseMenu(MenuBuilder menu, boolean allMenusAreClosing) { 398 if (mClosingActionMenu) { 399 return; 400 } 401 mClosingActionMenu = true; 402 mActivity.closeOptionsMenu(); 403 mDecorContentParent.dismissPopups(); 404 mClosingActionMenu = false; 405 } 406 407 @Override 408 public boolean onOpenSubMenu(MenuBuilder subMenu) { 409 return false; 410 } 411 412 @Override 413 public ActionMode startSupportActionMode(ActionMode.Callback callback) { 414 if (callback == null) { 415 throw new IllegalArgumentException("ActionMode callback can not be null."); 416 } 417 418 if (mActionMode != null) { 419 mActionMode.finish(); 420 } 421 422 final ActionMode.Callback wrappedCallback = new ActionModeCallbackWrapper(callback); 423 424 ActionBar ab = getSupportActionBar(); 425 if (ab != null) { 426 mActionMode = ab.startActionMode(wrappedCallback); 427 } 428 429 if (mActionMode != null) { 430 mActivity.onSupportActionModeStarted(mActionMode); 431 } 432 return mActionMode; 433 } 434 435 @Override 436 public void supportInvalidateOptionsMenu() { 437 final ActionBar ab = getSupportActionBar(); 438 if (ab != null && ab.invalidateOptionsMenu()) return; 439 440 if (mMenu != null) { 441 Bundle savedActionViewStates = new Bundle(); 442 mMenu.saveActionViewStates(savedActionViewStates); 443 if (savedActionViewStates.size() > 0) { 444 mPanelFrozenActionViewState = savedActionViewStates; 445 } 446 // This will be started again when the panel is prepared. 447 mMenu.stopDispatchingItemsChanged(); 448 mMenu.clear(); 449 } 450 mPanelRefreshContent = true; 451 452 // Prepare the options panel if we have an action bar 453 if (mDecorContentParent != null) { 454 mPanelIsPrepared = false; 455 preparePanel(); 456 } 457 } 458 459 @Override 460 ActionMode startSupportActionModeFromWindow(ActionMode.Callback callback) { 461 if (mActionMode != null) { 462 mActionMode.finish(); 463 } 464 465 final ActionMode.Callback wrappedCallback = new ActionModeCallbackWrapper(callback); 466 ActionMode mode = null; 467 468 if (mActionModeView == null) { 469 if (mIsFloating) { 470 mActionModeView = new ActionBarContextView(mActivity); 471 mActionModePopup = new PopupWindow(mActivity, null, 472 R.attr.actionModePopupWindowStyle); 473 mActionModePopup.setContentView(mActionModeView); 474 mActionModePopup.setWidth(ViewGroup.LayoutParams.MATCH_PARENT); 475 476 TypedValue heightValue = new TypedValue(); 477 mActivity.getTheme().resolveAttribute(R.attr.actionBarSize, heightValue, true); 478 final int height = TypedValue.complexToDimensionPixelSize(heightValue.data, 479 mActivity.getResources().getDisplayMetrics()); 480 mActionModeView.setContentHeight(height); 481 mActionModePopup.setHeight(ViewGroup.LayoutParams.WRAP_CONTENT); 482 mShowActionModePopup = new Runnable() { 483 public void run() { 484 mActionModePopup.showAtLocation( 485 mActionModeView, 486 Gravity.TOP | Gravity.FILL_HORIZONTAL, 0, 0); 487 } 488 }; 489 } else { 490 ViewStub stub = (ViewStub) mActivity.findViewById(R.id.action_mode_bar_stub); 491 if (stub != null) { 492 mActionModeView = (ActionBarContextView) stub.inflate(); 493 } 494 } 495 } 496 497 if (mActionModeView != null) { 498 mActionModeView.killMode(); 499 mode = new StandaloneActionMode(mActivity, mActionModeView, wrappedCallback, 500 mActionModePopup == null); 501 if (callback.onCreateActionMode(mode, mode.getMenu())) { 502 mode.invalidate(); 503 mActionModeView.initForMode(mode); 504 mActionModeView.setVisibility(View.VISIBLE); 505 mActionMode = mode; 506 if (mActionModePopup != null) { 507 mActivity.getWindow().getDecorView().post(mShowActionModePopup); 508 } 509 mActionModeView.sendAccessibilityEvent( 510 AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED); 511 } else { 512 mActionMode = null; 513 } 514 } 515 if (mActionMode != null && mActivity != null) { 516 mActivity.onSupportActionModeStarted(mActionMode); 517 } 518 return mActionMode; 519 } 520 521 private void reopenMenu(MenuBuilder menu, boolean toggleMenuMode) { 522 if (mDecorContentParent != null && mDecorContentParent.canShowOverflowMenu() && 523 (!ViewConfigurationCompat.hasPermanentMenuKey(ViewConfiguration.get(mActivity)) || 524 mDecorContentParent.isOverflowMenuShowPending())) { 525 if (!mDecorContentParent.isOverflowMenuShowing() || !toggleMenuMode) { 526 mDecorContentParent.showOverflowMenu(); 527 } else { 528 mDecorContentParent.hideOverflowMenu(); 529 } 530 return; 531 } 532 533 menu.close(); 534 } 535 536 private MenuView getListMenuView(Context context, MenuPresenter.Callback cb) { 537 if (mMenu == null) { 538 return null; 539 } 540 541 if (mListMenuPresenter == null) { 542 TypedArray a = context.obtainStyledAttributes(R.styleable.Theme); 543 final int listPresenterTheme = a.getResourceId( 544 R.styleable.Theme_panelMenuListTheme, 545 R.style.Theme_AppCompat_CompactMenu); 546 a.recycle(); 547 548 mListMenuPresenter = new ListMenuPresenter( 549 R.layout.abc_list_menu_item_layout, listPresenterTheme); 550 mListMenuPresenter.setCallback(cb); 551 mMenu.addMenuPresenter(mListMenuPresenter); 552 } else { 553 // Make sure we update the ListView 554 mListMenuPresenter.updateMenuView(false); 555 } 556 557 return mListMenuPresenter.getMenuView(new FrameLayout(context)); 558 } 559 560 @Override 561 public boolean onBackPressed() { 562 // Back cancels action modes first. 563 if (mActionMode != null) { 564 mActionMode.finish(); 565 return true; 566 } 567 568 // Next collapse any expanded action views. 569 ActionBar ab = getSupportActionBar(); 570 if (ab != null && ab.collapseActionView()) { 571 return true; 572 } 573 574 return false; 575 } 576 577 @Override 578 void setSupportProgressBarVisibility(boolean visible) { 579 updateProgressBars(visible ? Window.PROGRESS_VISIBILITY_ON : 580 Window.PROGRESS_VISIBILITY_OFF); 581 } 582 583 @Override 584 void setSupportProgressBarIndeterminateVisibility(boolean visible) { 585 updateProgressBars(visible ? Window.PROGRESS_VISIBILITY_ON : 586 Window.PROGRESS_VISIBILITY_OFF); 587 } 588 589 @Override 590 void setSupportProgressBarIndeterminate(boolean indeterminate) { 591 updateProgressBars(indeterminate ? Window.PROGRESS_INDETERMINATE_ON 592 : Window.PROGRESS_INDETERMINATE_OFF); 593 } 594 595 @Override 596 void setSupportProgress(int progress) { 597 updateProgressBars(Window.PROGRESS_START + progress); 598 } 599 600 @Override 601 int getHomeAsUpIndicatorAttrId() { 602 return R.attr.homeAsUpIndicator; 603 } 604 605 /** 606 * Progress Bar function. Mostly extracted from PhoneWindow.java 607 */ 608 private void updateProgressBars(int value) { 609 ProgressBarCompat circularProgressBar = getCircularProgressBar(); 610 ProgressBarCompat horizontalProgressBar = getHorizontalProgressBar(); 611 612 if (value == Window.PROGRESS_VISIBILITY_ON) { 613 if (mFeatureProgress) { 614 int level = horizontalProgressBar.getProgress(); 615 int visibility = (horizontalProgressBar.isIndeterminate() || level < 10000) ? 616 View.VISIBLE : View.INVISIBLE; 617 horizontalProgressBar.setVisibility(visibility); 618 } 619 if (mFeatureIndeterminateProgress) { 620 circularProgressBar.setVisibility(View.VISIBLE); 621 } 622 } else if (value == Window.PROGRESS_VISIBILITY_OFF) { 623 if (mFeatureProgress) { 624 horizontalProgressBar.setVisibility(View.GONE); 625 } 626 if (mFeatureIndeterminateProgress) { 627 circularProgressBar.setVisibility(View.GONE); 628 } 629 } else if (value == Window.PROGRESS_INDETERMINATE_ON) { 630 horizontalProgressBar.setIndeterminate(true); 631 } else if (value == Window.PROGRESS_INDETERMINATE_OFF) { 632 horizontalProgressBar.setIndeterminate(false); 633 } else if (Window.PROGRESS_START <= value && value <= Window.PROGRESS_END) { 634 // We want to set the progress value before testing for visibility 635 // so that when the progress bar becomes visible again, it has the 636 // correct level. 637 horizontalProgressBar.setProgress(value - Window.PROGRESS_START); 638 639 if (value < Window.PROGRESS_END) { 640 showProgressBars(horizontalProgressBar, circularProgressBar); 641 } else { 642 hideProgressBars(horizontalProgressBar, circularProgressBar); 643 } 644 } 645 } 646 647 private void showProgressBars(ProgressBarCompat horizontalProgressBar, 648 ProgressBarCompat spinnyProgressBar) { 649 if (mFeatureIndeterminateProgress && spinnyProgressBar.getVisibility() == View.INVISIBLE) { 650 spinnyProgressBar.setVisibility(View.VISIBLE); 651 } 652 // Only show the progress bars if the primary progress is not complete 653 if (mFeatureProgress && horizontalProgressBar.getProgress() < 10000) { 654 horizontalProgressBar.setVisibility(View.VISIBLE); 655 } 656 } 657 658 private void hideProgressBars(ProgressBarCompat horizontalProgressBar, 659 ProgressBarCompat spinnyProgressBar) { 660 if (mFeatureIndeterminateProgress && spinnyProgressBar.getVisibility() == View.VISIBLE) { 661 spinnyProgressBar.setVisibility(View.INVISIBLE); 662 } 663 if (mFeatureProgress && horizontalProgressBar.getVisibility() == View.VISIBLE) { 664 horizontalProgressBar.setVisibility(View.INVISIBLE); 665 } 666 } 667 668 private ProgressBarCompat getCircularProgressBar() { 669 ProgressBarCompat pb = (ProgressBarCompat) mActivity.findViewById(R.id.progress_circular); 670 if (pb != null) { 671 pb.setVisibility(View.INVISIBLE); 672 } 673 return pb; 674 } 675 676 private ProgressBarCompat getHorizontalProgressBar() { 677 ProgressBarCompat pb = (ProgressBarCompat) mActivity.findViewById(R.id.progress_horizontal); 678 if (pb != null) { 679 pb.setVisibility(View.INVISIBLE); 680 } 681 return pb; 682 } 683 684 private boolean initializePanelMenu() { 685 Context context = mActivity; 686 687 if (mDecorContentParent != null) { 688 final TypedValue outValue = new TypedValue(); 689 final Resources.Theme baseTheme = context.getTheme(); 690 baseTheme.resolveAttribute(R.attr.actionBarTheme, outValue, true); 691 692 Resources.Theme widgetTheme = null; 693 if (outValue.resourceId != 0) { 694 widgetTheme = context.getResources().newTheme(); 695 widgetTheme.setTo(baseTheme); 696 widgetTheme.applyStyle(outValue.resourceId, true); 697 widgetTheme.resolveAttribute( 698 R.attr.actionBarWidgetTheme, outValue, true); 699 } else { 700 baseTheme.resolveAttribute( 701 R.attr.actionBarWidgetTheme, outValue, true); 702 } 703 704 if (outValue.resourceId != 0) { 705 if (widgetTheme == null) { 706 widgetTheme = context.getResources().newTheme(); 707 widgetTheme.setTo(baseTheme); 708 } 709 widgetTheme.applyStyle(outValue.resourceId, true); 710 } 711 712 if (widgetTheme != null) { 713 context = new ContextThemeWrapper(context, 0); 714 context.getTheme().setTo(widgetTheme); 715 } 716 } 717 718 mMenu = new MenuBuilder(context); 719 mMenu.setCallback(this); 720 721 return true; 722 } 723 724 private boolean preparePanel() { 725 // Already prepared (isPrepared will be reset to false later) 726 if (mPanelIsPrepared) { 727 return true; 728 } 729 730 if (mDecorContentParent != null) { 731 // Enforce ordering guarantees around events so that the action bar never 732 // dispatches menu-related events before the panel is prepared. 733 mDecorContentParent.setMenuPrepared(); 734 } 735 736 // Init the panel state's menu--return false if init failed 737 if (mMenu == null || mPanelRefreshContent) { 738 if (mMenu == null) { 739 if (!initializePanelMenu() || (mMenu == null)) { 740 return false; 741 } 742 } 743 744 if (mDecorContentParent != null) { 745 mDecorContentParent.setMenu(mMenu, this); 746 } 747 748 // Creating the panel menu will involve a lot of manipulation; 749 // don't dispatch change events to presenters until we're done. 750 mMenu.stopDispatchingItemsChanged(); 751 752 // Call callback, and return if it doesn't want to display menu. 753 if (!mActivity.superOnCreatePanelMenu(Window.FEATURE_OPTIONS_PANEL, mMenu)) { 754 // Ditch the menu created above 755 mMenu = null; 756 757 if (mDecorContentParent != null) { 758 // Don't show it in the action bar either 759 mDecorContentParent.setMenu(null, this); 760 } 761 762 return false; 763 } 764 765 mPanelRefreshContent = false; 766 } 767 768 // Preparing the panel menu can involve a lot of manipulation; 769 // don't dispatch change events to presenters until we're done. 770 mMenu.stopDispatchingItemsChanged(); 771 772 // Restore action view state before we prepare. This gives apps 773 // an opportunity to override frozen/restored state in onPrepare. 774 if (mPanelFrozenActionViewState != null) { 775 mMenu.restoreActionViewStates(mPanelFrozenActionViewState); 776 mPanelFrozenActionViewState = null; 777 } 778 779 // Callback and return if the callback does not want to show the menu 780 if (!mActivity.superOnPreparePanel(Window.FEATURE_OPTIONS_PANEL, null, mMenu)) { 781 if (mDecorContentParent != null) { 782 // The app didn't want to show the menu for now but it still exists. 783 // Clear it out of the action bar. 784 mDecorContentParent.setMenu(null, this); 785 } 786 mMenu.startDispatchingItemsChanged(); 787 return false; 788 } 789 790 mMenu.startDispatchingItemsChanged(); 791 792 // Set other state 793 mPanelIsPrepared = true; 794 795 return true; 796 } 797 798 /** 799 * Clears out internal reference when the action mode is destroyed. 800 */ 801 private class ActionModeCallbackWrapper implements ActionMode.Callback { 802 private ActionMode.Callback mWrapped; 803 804 public ActionModeCallbackWrapper(ActionMode.Callback wrapped) { 805 mWrapped = wrapped; 806 } 807 808 public boolean onCreateActionMode(ActionMode mode, Menu menu) { 809 return mWrapped.onCreateActionMode(mode, menu); 810 } 811 812 public boolean onPrepareActionMode(ActionMode mode, Menu menu) { 813 return mWrapped.onPrepareActionMode(mode, menu); 814 } 815 816 public boolean onActionItemClicked(ActionMode mode, MenuItem item) { 817 return mWrapped.onActionItemClicked(mode, item); 818 } 819 820 public void onDestroyActionMode(ActionMode mode) { 821 mWrapped.onDestroyActionMode(mode); 822 if (mActionModePopup != null) { 823 mActivity.getWindow().getDecorView().removeCallbacks(mShowActionModePopup); 824 mActionModePopup.dismiss(); 825 } else if (mActionModeView != null) { 826 mActionModeView.setVisibility(View.GONE); 827 } 828 if (mActionModeView != null) { 829 mActionModeView.removeAllViews(); 830 } 831 if (mActivity != null) { 832 try { 833 mActivity.onSupportActionModeFinished(mActionMode); 834 } catch (AbstractMethodError ame) { 835 // Older apps might not implement this callback method. 836 } 837 } 838 mActionMode = null; 839 } 840 } 841 842} 843