AppCompatDelegateImplV7.java revision d15ee7df01f2f48b536a610c4739f33b226d3f81
16386aac7ea9be44d23dcea28d9a02110c174e988Chris Banes/* 26386aac7ea9be44d23dcea28d9a02110c174e988Chris Banes * Copyright (C) 2013 The Android Open Source Project 36386aac7ea9be44d23dcea28d9a02110c174e988Chris Banes * 46386aac7ea9be44d23dcea28d9a02110c174e988Chris Banes * Licensed under the Apache License, Version 2.0 (the "License"); 56386aac7ea9be44d23dcea28d9a02110c174e988Chris Banes * you may not use this file except in compliance with the License. 66386aac7ea9be44d23dcea28d9a02110c174e988Chris Banes * You may obtain a copy of the License at 76386aac7ea9be44d23dcea28d9a02110c174e988Chris Banes * 86386aac7ea9be44d23dcea28d9a02110c174e988Chris Banes * http://www.apache.org/licenses/LICENSE-2.0 96386aac7ea9be44d23dcea28d9a02110c174e988Chris Banes * 106386aac7ea9be44d23dcea28d9a02110c174e988Chris Banes * Unless required by applicable law or agreed to in writing, software 116386aac7ea9be44d23dcea28d9a02110c174e988Chris Banes * distributed under the License is distributed on an "AS IS" BASIS, 126386aac7ea9be44d23dcea28d9a02110c174e988Chris Banes * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 136386aac7ea9be44d23dcea28d9a02110c174e988Chris Banes * See the License for the specific language governing permissions and 146386aac7ea9be44d23dcea28d9a02110c174e988Chris Banes * limitations under the License. 156386aac7ea9be44d23dcea28d9a02110c174e988Chris Banes */ 166386aac7ea9be44d23dcea28d9a02110c174e988Chris Banes 176386aac7ea9be44d23dcea28d9a02110c174e988Chris Banespackage android.support.v7.app; 186386aac7ea9be44d23dcea28d9a02110c174e988Chris Banes 196386aac7ea9be44d23dcea28d9a02110c174e988Chris Banesimport android.content.Context; 206386aac7ea9be44d23dcea28d9a02110c174e988Chris Banesimport android.content.res.Configuration; 2161c0bbe56a13fe55ce91a5b1d64e751164ecb894Chris Banesimport android.content.res.Resources; 226386aac7ea9be44d23dcea28d9a02110c174e988Chris Banesimport android.content.res.TypedArray; 23ec3f49d21a507835c1f50ce5600000b587a2af08Chris Banesimport android.graphics.Rect; 24469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banesimport android.os.Build; 258902df1bf0006a156503d40b1fc8a01f95d5b806Chris Banesimport android.os.Bundle; 2600d183885b54de433e43118d3032340f40cac8c0Chris Banesimport android.os.Parcel; 2700d183885b54de433e43118d3032340f40cac8c0Chris Banesimport android.os.Parcelable; 28469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banesimport android.support.annotation.NonNull; 2949c78900da0d43140fb602431fb93212bd7f6c70Chris Banesimport android.support.v4.app.NavUtils; 30ea4f700ac38424954c56df5138ff794def50b019Chris Banesimport android.support.v4.view.OnApplyWindowInsetsListener; 3103fc11b659da1645507062bddda450136e13af35Chris Banesimport android.support.v4.view.ViewCompat; 3249c78900da0d43140fb602431fb93212bd7f6c70Chris Banesimport android.support.v4.view.ViewConfigurationCompat; 33ea4f700ac38424954c56df5138ff794def50b019Chris Banesimport android.support.v4.view.WindowInsetsCompat; 346386aac7ea9be44d23dcea28d9a02110c174e988Chris Banesimport android.support.v7.appcompat.R; 35b73824b81c57b0a6821be9296a053ce4e516e583Chris Banesimport android.support.v7.internal.VersionUtils; 3649c78900da0d43140fb602431fb93212bd7f6c70Chris Banesimport android.support.v7.internal.app.ToolbarActionBar; 3700d183885b54de433e43118d3032340f40cac8c0Chris Banesimport android.support.v7.internal.app.WindowCallback; 3849c78900da0d43140fb602431fb93212bd7f6c70Chris Banesimport android.support.v7.internal.app.WindowDecorActionBar; 394c2a95906254748cb9a843b061288265d6e185a9Chris Banesimport android.support.v7.internal.view.StandaloneActionMode; 406386aac7ea9be44d23dcea28d9a02110c174e988Chris Banesimport android.support.v7.internal.view.menu.ListMenuPresenter; 416386aac7ea9be44d23dcea28d9a02110c174e988Chris Banesimport android.support.v7.internal.view.menu.MenuBuilder; 426386aac7ea9be44d23dcea28d9a02110c174e988Chris Banesimport android.support.v7.internal.view.menu.MenuPresenter; 436386aac7ea9be44d23dcea28d9a02110c174e988Chris Banesimport android.support.v7.internal.view.menu.MenuView; 444c2a95906254748cb9a843b061288265d6e185a9Chris Banesimport android.support.v7.internal.widget.ActionBarContextView; 4549c78900da0d43140fb602431fb93212bd7f6c70Chris Banesimport android.support.v7.internal.widget.DecorContentParent; 46ea4f700ac38424954c56df5138ff794def50b019Chris Banesimport android.support.v7.internal.widget.FitWindowsViewGroup; 47012047c60d03e61498955b7fa3e9cb9b409fbad8Chris Banesimport android.support.v7.internal.widget.TintAutoCompleteTextView; 48a9585dae398a69dd67797e7ca86f44ffcabd9e86Chris Banesimport android.support.v7.internal.widget.TintButton; 49415f740df4981ef2f5fb462a50c7cf095cc21128Chris Banesimport android.support.v7.internal.widget.TintCheckBox; 50415f740df4981ef2f5fb462a50c7cf095cc21128Chris Banesimport android.support.v7.internal.widget.TintCheckedTextView; 51469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banesimport android.support.v7.internal.widget.TintEditText; 52012047c60d03e61498955b7fa3e9cb9b409fbad8Chris Banesimport android.support.v7.internal.widget.TintMultiAutoCompleteTextView; 53415f740df4981ef2f5fb462a50c7cf095cc21128Chris Banesimport android.support.v7.internal.widget.TintRadioButton; 54a9585dae398a69dd67797e7ca86f44ffcabd9e86Chris Banesimport android.support.v7.internal.widget.TintRatingBar; 55415f740df4981ef2f5fb462a50c7cf095cc21128Chris Banesimport android.support.v7.internal.widget.TintSpinner; 564bd5cbd6ca4f1e5ed43217b808068a48f937feabChris Banesimport android.support.v7.internal.widget.ViewStubCompat; 57ec3f49d21a507835c1f50ce5600000b587a2af08Chris Banesimport android.support.v7.internal.widget.ViewUtils; 58d8222dedaacae30fa03bee346ebf42ee75b39928Chris Banesimport android.support.v7.view.ActionMode; 5949c78900da0d43140fb602431fb93212bd7f6c70Chris Banesimport android.support.v7.widget.Toolbar; 60cc7aada3ee922cfb38eeb36ee696cc73dcbae0a4Chris Banesimport android.util.AndroidRuntimeException; 61469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banesimport android.util.AttributeSet; 6256fd50144df518461398a9b3397ee4842b346708Chris Banesimport android.util.DisplayMetrics; 6356fd50144df518461398a9b3397ee4842b346708Chris Banesimport android.util.TypedValue; 6461c0bbe56a13fe55ce91a5b1d64e751164ecb894Chris Banesimport android.view.ContextThemeWrapper; 654c2a95906254748cb9a843b061288265d6e185a9Chris Banesimport android.view.Gravity; 6600d183885b54de433e43118d3032340f40cac8c0Chris Banesimport android.view.KeyCharacterMap; 67dea1122145ed85590d298a3a9d88ba9f9e2f5f46Chris Banesimport android.view.KeyEvent; 68dea1122145ed85590d298a3a9d88ba9f9e2f5f46Chris Banesimport android.view.LayoutInflater; 6930837f1095c803f332f4a1c3f0917c8afdd50156Adam Powellimport android.view.Menu; 7030837f1095c803f332f4a1c3f0917c8afdd50156Adam Powellimport android.view.MenuItem; 716386aac7ea9be44d23dcea28d9a02110c174e988Chris Banesimport android.view.View; 7249c78900da0d43140fb602431fb93212bd7f6c70Chris Banesimport android.view.ViewConfiguration; 736386aac7ea9be44d23dcea28d9a02110c174e988Chris Banesimport android.view.ViewGroup; 746386aac7ea9be44d23dcea28d9a02110c174e988Chris Banesimport android.view.Window; 754c2a95906254748cb9a843b061288265d6e185a9Chris Banesimport android.view.accessibility.AccessibilityEvent; 7630837f1095c803f332f4a1c3f0917c8afdd50156Adam Powellimport android.widget.FrameLayout; 774c2a95906254748cb9a843b061288265d6e185a9Chris Banesimport android.widget.PopupWindow; 786386aac7ea9be44d23dcea28d9a02110c174e988Chris Banes 79469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banesimport static android.support.v4.view.WindowCompat.FEATURE_ACTION_BAR; 80469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banesimport static android.support.v4.view.WindowCompat.FEATURE_ACTION_BAR_OVERLAY; 81469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banesimport static android.support.v4.view.WindowCompat.FEATURE_ACTION_MODE_OVERLAY; 8200d183885b54de433e43118d3032340f40cac8c0Chris Banesimport static android.view.Window.FEATURE_OPTIONS_PANEL; 8300d183885b54de433e43118d3032340f40cac8c0Chris Banes 8403fc11b659da1645507062bddda450136e13af35Chris Banesclass ActionBarActivityDelegateBase extends ActionBarActivityDelegate 8503fc11b659da1645507062bddda450136e13af35Chris Banes implements MenuBuilder.Callback { 8630837f1095c803f332f4a1c3f0917c8afdd50156Adam Powell private static final String TAG = "ActionBarActivityDelegateBase"; 876386aac7ea9be44d23dcea28d9a02110c174e988Chris Banes 8849c78900da0d43140fb602431fb93212bd7f6c70Chris Banes private DecorContentParent mDecorContentParent; 8903fc11b659da1645507062bddda450136e13af35Chris Banes private ActionMenuPresenterCallback mActionMenuPresenterCallback; 9003fc11b659da1645507062bddda450136e13af35Chris Banes private PanelMenuPresenterCallback mPanelMenuPresenterCallback; 9103fc11b659da1645507062bddda450136e13af35Chris Banes 924c2a95906254748cb9a843b061288265d6e185a9Chris Banes ActionMode mActionMode; 934c2a95906254748cb9a843b061288265d6e185a9Chris Banes ActionBarContextView mActionModeView; 944c2a95906254748cb9a843b061288265d6e185a9Chris Banes PopupWindow mActionModePopup; 954c2a95906254748cb9a843b061288265d6e185a9Chris Banes Runnable mShowActionModePopup; 965a2bcc375e046c5b6644dcc4d331d3fca0778aedChris Banes 975a2bcc375e046c5b6644dcc4d331d3fca0778aedChris Banes // true if we have installed a window sub-decor layout. 985a2bcc375e046c5b6644dcc4d331d3fca0778aedChris Banes private boolean mSubDecorInstalled; 9903fc11b659da1645507062bddda450136e13af35Chris Banes private ViewGroup mWindowDecor; 100ec3f49d21a507835c1f50ce5600000b587a2af08Chris Banes private ViewGroup mSubDecor; 101ec3f49d21a507835c1f50ce5600000b587a2af08Chris Banes 102ec3f49d21a507835c1f50ce5600000b587a2af08Chris Banes private View mStatusGuard; 103d8222dedaacae30fa03bee346ebf42ee75b39928Chris Banes 104f53c7bf3146bf9bcba46324f9f06449df475be36Chris Banes private CharSequence mTitleToSet; 105f53c7bf3146bf9bcba46324f9f06449df475be36Chris Banes 106ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes // Used to keep track of Progress Bar Window features 107ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes private boolean mFeatureProgress, mFeatureIndeterminateProgress; 108ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes 1098902df1bf0006a156503d40b1fc8a01f95d5b806Chris Banes // Used for emulating PanelFeatureState 1108902df1bf0006a156503d40b1fc8a01f95d5b806Chris Banes private boolean mClosingActionMenu; 11100d183885b54de433e43118d3032340f40cac8c0Chris Banes private PanelFeatureState[] mPanels; 11200d183885b54de433e43118d3032340f40cac8c0Chris Banes private PanelFeatureState mPreparedPanel; 113556ac47ce764a4a9320b5ac914536e9da2524176Chris Banes 11403fc11b659da1645507062bddda450136e13af35Chris Banes private boolean mInvalidatePanelMenuPosted; 11500d183885b54de433e43118d3032340f40cac8c0Chris Banes private int mInvalidatePanelMenuFeatures; 11603fc11b659da1645507062bddda450136e13af35Chris Banes private final Runnable mInvalidatePanelMenuRunnable = new Runnable() { 11703fc11b659da1645507062bddda450136e13af35Chris Banes @Override 11803fc11b659da1645507062bddda450136e13af35Chris Banes public void run() { 11900d183885b54de433e43118d3032340f40cac8c0Chris Banes if ((mInvalidatePanelMenuFeatures & 1 << FEATURE_OPTIONS_PANEL) != 0) { 12000d183885b54de433e43118d3032340f40cac8c0Chris Banes doInvalidatePanelMenu(FEATURE_OPTIONS_PANEL); 12100d183885b54de433e43118d3032340f40cac8c0Chris Banes } 12200d183885b54de433e43118d3032340f40cac8c0Chris Banes if ((mInvalidatePanelMenuFeatures & 1 << FEATURE_ACTION_BAR) != 0) { 12300d183885b54de433e43118d3032340f40cac8c0Chris Banes doInvalidatePanelMenu(FEATURE_ACTION_BAR); 12400d183885b54de433e43118d3032340f40cac8c0Chris Banes } 12500d183885b54de433e43118d3032340f40cac8c0Chris Banes mInvalidatePanelMenuPosted = false; 12600d183885b54de433e43118d3032340f40cac8c0Chris Banes mInvalidatePanelMenuFeatures = 0; 12703fc11b659da1645507062bddda450136e13af35Chris Banes } 12803fc11b659da1645507062bddda450136e13af35Chris Banes }; 12903fc11b659da1645507062bddda450136e13af35Chris Banes 13049c78900da0d43140fb602431fb93212bd7f6c70Chris Banes private boolean mEnableDefaultActionBarUp; 13149c78900da0d43140fb602431fb93212bd7f6c70Chris Banes 132da0b9d63d6f940cbfd5b526c3f81858aeadcb7e8Chris Banes private ListMenuPresenter mToolbarListMenuPresenter; 133da0b9d63d6f940cbfd5b526c3f81858aeadcb7e8Chris Banes 1347efc56b68ff933dfeeac81dd2d8a32096b90f0f4Adam Powell private Rect mTempRect1; 1357efc56b68ff933dfeeac81dd2d8a32096b90f0f4Adam Powell private Rect mTempRect2; 1367efc56b68ff933dfeeac81dd2d8a32096b90f0f4Adam Powell 137f2b7cd67036d78fd5b487b0a2dab28aee11d9c88Adam Powell ActionBarActivityDelegateBase(ActionBarActivity activity) { 1383954d59cb6073615ead9dd34cbdba9e16b8c5b6fChris Banes super(activity); 1396386aac7ea9be44d23dcea28d9a02110c174e988Chris Banes } 1406386aac7ea9be44d23dcea28d9a02110c174e988Chris Banes 1416386aac7ea9be44d23dcea28d9a02110c174e988Chris Banes @Override 14249c78900da0d43140fb602431fb93212bd7f6c70Chris Banes void onCreate(Bundle savedInstanceState) { 14349c78900da0d43140fb602431fb93212bd7f6c70Chris Banes super.onCreate(savedInstanceState); 14449c78900da0d43140fb602431fb93212bd7f6c70Chris Banes 14503fc11b659da1645507062bddda450136e13af35Chris Banes mWindowDecor = (ViewGroup) mActivity.getWindow().getDecorView(); 14603fc11b659da1645507062bddda450136e13af35Chris Banes 14749c78900da0d43140fb602431fb93212bd7f6c70Chris Banes if (NavUtils.getParentActivityName(mActivity) != null) { 148cc7aada3ee922cfb38eeb36ee696cc73dcbae0a4Chris Banes // Peek at the Action Bar and update it if it already exists 149cc7aada3ee922cfb38eeb36ee696cc73dcbae0a4Chris Banes ActionBar ab = peekSupportActionBar(); 15049c78900da0d43140fb602431fb93212bd7f6c70Chris Banes if (ab == null) { 15149c78900da0d43140fb602431fb93212bd7f6c70Chris Banes mEnableDefaultActionBarUp = true; 15249c78900da0d43140fb602431fb93212bd7f6c70Chris Banes } else { 15349c78900da0d43140fb602431fb93212bd7f6c70Chris Banes ab.setDefaultDisplayHomeAsUpEnabled(true); 15449c78900da0d43140fb602431fb93212bd7f6c70Chris Banes } 15549c78900da0d43140fb602431fb93212bd7f6c70Chris Banes } 15649c78900da0d43140fb602431fb93212bd7f6c70Chris Banes } 15749c78900da0d43140fb602431fb93212bd7f6c70Chris Banes 15849c78900da0d43140fb602431fb93212bd7f6c70Chris Banes @Override 1596386aac7ea9be44d23dcea28d9a02110c174e988Chris Banes public ActionBar createSupportActionBar() { 16030837f1095c803f332f4a1c3f0917c8afdd50156Adam Powell ensureSubDecor(); 16149c78900da0d43140fb602431fb93212bd7f6c70Chris Banes ActionBar ab = new WindowDecorActionBar(mActivity, mOverlayActionBar); 16249c78900da0d43140fb602431fb93212bd7f6c70Chris Banes ab.setDefaultDisplayHomeAsUpEnabled(mEnableDefaultActionBarUp); 16349c78900da0d43140fb602431fb93212bd7f6c70Chris Banes return ab; 16449c78900da0d43140fb602431fb93212bd7f6c70Chris Banes } 16549c78900da0d43140fb602431fb93212bd7f6c70Chris Banes 16649c78900da0d43140fb602431fb93212bd7f6c70Chris Banes @Override 16749c78900da0d43140fb602431fb93212bd7f6c70Chris Banes void setSupportActionBar(Toolbar toolbar) { 168da0b9d63d6f940cbfd5b526c3f81858aeadcb7e8Chris Banes final ActionBar ab = getSupportActionBar(); 169da0b9d63d6f940cbfd5b526c3f81858aeadcb7e8Chris Banes if (ab instanceof WindowDecorActionBar) { 17049c78900da0d43140fb602431fb93212bd7f6c70Chris Banes throw new IllegalStateException("This Activity already has an action bar supplied " + 17149c78900da0d43140fb602431fb93212bd7f6c70Chris Banes "by the window decor. Do not request Window.FEATURE_ACTION_BAR and set " + 17249c78900da0d43140fb602431fb93212bd7f6c70Chris Banes "windowActionBar to false in your theme to use a Toolbar instead."); 173da0b9d63d6f940cbfd5b526c3f81858aeadcb7e8Chris Banes } else if (ab instanceof ToolbarActionBar) { 174da0b9d63d6f940cbfd5b526c3f81858aeadcb7e8Chris Banes // Make sure we reset the old toolbar AB's list menu presenter 175da0b9d63d6f940cbfd5b526c3f81858aeadcb7e8Chris Banes ((ToolbarActionBar) ab).setListMenuPresenter(null); 17649c78900da0d43140fb602431fb93212bd7f6c70Chris Banes } 177da0b9d63d6f940cbfd5b526c3f81858aeadcb7e8Chris Banes 178a6e86333cb4de18fc9b86746a49643e213db7c18Chris Banes // Need to make sure we give the action bar the default window callback. Otherwise multiple 179a6e86333cb4de18fc9b86746a49643e213db7c18Chris Banes // setSupportActionBar() calls lead to memory leaks 1800b216f2263135782c361e122892a12156d5d2ce1Chris Banes ToolbarActionBar tbab = new ToolbarActionBar(toolbar, mActivity.getTitle(), 181da0b9d63d6f940cbfd5b526c3f81858aeadcb7e8Chris Banes mActivity.getWindow(), mDefaultWindowCallback); 182da0b9d63d6f940cbfd5b526c3f81858aeadcb7e8Chris Banes ensureToolbarListMenuPresenter(); 183da0b9d63d6f940cbfd5b526c3f81858aeadcb7e8Chris Banes tbab.setListMenuPresenter(mToolbarListMenuPresenter); 1840b216f2263135782c361e122892a12156d5d2ce1Chris Banes setSupportActionBar(tbab); 1850b216f2263135782c361e122892a12156d5d2ce1Chris Banes setWindowCallback(tbab.getWrappedWindowCallback()); 1860b216f2263135782c361e122892a12156d5d2ce1Chris Banes tbab.invalidateOptionsMenu(); 1876386aac7ea9be44d23dcea28d9a02110c174e988Chris Banes } 1886386aac7ea9be44d23dcea28d9a02110c174e988Chris Banes 1896386aac7ea9be44d23dcea28d9a02110c174e988Chris Banes @Override 1906386aac7ea9be44d23dcea28d9a02110c174e988Chris Banes public void onConfigurationChanged(Configuration newConfig) { 1916386aac7ea9be44d23dcea28d9a02110c174e988Chris Banes // If this is called before sub-decor is installed, ActionBar will not 1926386aac7ea9be44d23dcea28d9a02110c174e988Chris Banes // be properly initialized. 1935a2bcc375e046c5b6644dcc4d331d3fca0778aedChris Banes if (mHasActionBar && mSubDecorInstalled) { 1946386aac7ea9be44d23dcea28d9a02110c174e988Chris Banes // Note: The action bar will need to access 1956386aac7ea9be44d23dcea28d9a02110c174e988Chris Banes // view changes from superclass. 19649c78900da0d43140fb602431fb93212bd7f6c70Chris Banes ActionBar ab = getSupportActionBar(); 19749c78900da0d43140fb602431fb93212bd7f6c70Chris Banes if (ab != null) { 19849c78900da0d43140fb602431fb93212bd7f6c70Chris Banes ab.onConfigurationChanged(newConfig); 19949c78900da0d43140fb602431fb93212bd7f6c70Chris Banes } 2006386aac7ea9be44d23dcea28d9a02110c174e988Chris Banes } 2016386aac7ea9be44d23dcea28d9a02110c174e988Chris Banes } 2026386aac7ea9be44d23dcea28d9a02110c174e988Chris Banes 2036386aac7ea9be44d23dcea28d9a02110c174e988Chris Banes @Override 204a1fae63dbeeef71c2daa25bfcaa2348bffc369aaChris Banes public void onStop() { 20549c78900da0d43140fb602431fb93212bd7f6c70Chris Banes ActionBar ab = getSupportActionBar(); 206a1fae63dbeeef71c2daa25bfcaa2348bffc369aaChris Banes if (ab != null) { 207a1fae63dbeeef71c2daa25bfcaa2348bffc369aaChris Banes ab.setShowHideAnimationEnabled(false); 208a1fae63dbeeef71c2daa25bfcaa2348bffc369aaChris Banes } 209a1fae63dbeeef71c2daa25bfcaa2348bffc369aaChris Banes } 210a1fae63dbeeef71c2daa25bfcaa2348bffc369aaChris Banes 211a1fae63dbeeef71c2daa25bfcaa2348bffc369aaChris Banes @Override 212a1fae63dbeeef71c2daa25bfcaa2348bffc369aaChris Banes public void onPostResume() { 21349c78900da0d43140fb602431fb93212bd7f6c70Chris Banes ActionBar ab = getSupportActionBar(); 214a1fae63dbeeef71c2daa25bfcaa2348bffc369aaChris Banes if (ab != null) { 215a1fae63dbeeef71c2daa25bfcaa2348bffc369aaChris Banes ab.setShowHideAnimationEnabled(true); 216a1fae63dbeeef71c2daa25bfcaa2348bffc369aaChris Banes } 217a1fae63dbeeef71c2daa25bfcaa2348bffc369aaChris Banes } 218a1fae63dbeeef71c2daa25bfcaa2348bffc369aaChris Banes 219a1fae63dbeeef71c2daa25bfcaa2348bffc369aaChris Banes @Override 2206386aac7ea9be44d23dcea28d9a02110c174e988Chris Banes public void setContentView(View v) { 2216386aac7ea9be44d23dcea28d9a02110c174e988Chris Banes ensureSubDecor(); 22256fd50144df518461398a9b3397ee4842b346708Chris Banes ViewGroup contentParent = (ViewGroup) mActivity.findViewById(android.R.id.content); 22356fd50144df518461398a9b3397ee4842b346708Chris Banes contentParent.removeAllViews(); 22456fd50144df518461398a9b3397ee4842b346708Chris Banes contentParent.addView(v); 225d64322f4b9686fabfd5a03f402d50a8e3fe5adedChris Banes mActivity.onSupportContentChanged(); 2266386aac7ea9be44d23dcea28d9a02110c174e988Chris Banes } 2276386aac7ea9be44d23dcea28d9a02110c174e988Chris Banes 2286386aac7ea9be44d23dcea28d9a02110c174e988Chris Banes @Override 2296386aac7ea9be44d23dcea28d9a02110c174e988Chris Banes public void setContentView(int resId) { 2306386aac7ea9be44d23dcea28d9a02110c174e988Chris Banes ensureSubDecor(); 23156fd50144df518461398a9b3397ee4842b346708Chris Banes ViewGroup contentParent = (ViewGroup) mActivity.findViewById(android.R.id.content); 23256fd50144df518461398a9b3397ee4842b346708Chris Banes contentParent.removeAllViews(); 23356fd50144df518461398a9b3397ee4842b346708Chris Banes mActivity.getLayoutInflater().inflate(resId, contentParent); 234d64322f4b9686fabfd5a03f402d50a8e3fe5adedChris Banes mActivity.onSupportContentChanged(); 2356386aac7ea9be44d23dcea28d9a02110c174e988Chris Banes } 2366386aac7ea9be44d23dcea28d9a02110c174e988Chris Banes 2376386aac7ea9be44d23dcea28d9a02110c174e988Chris Banes @Override 2386386aac7ea9be44d23dcea28d9a02110c174e988Chris Banes public void setContentView(View v, ViewGroup.LayoutParams lp) { 2396386aac7ea9be44d23dcea28d9a02110c174e988Chris Banes ensureSubDecor(); 24056fd50144df518461398a9b3397ee4842b346708Chris Banes ViewGroup contentParent = (ViewGroup) mActivity.findViewById(android.R.id.content); 24156fd50144df518461398a9b3397ee4842b346708Chris Banes contentParent.removeAllViews(); 24256fd50144df518461398a9b3397ee4842b346708Chris Banes contentParent.addView(v, lp); 243d64322f4b9686fabfd5a03f402d50a8e3fe5adedChris Banes mActivity.onSupportContentChanged(); 2446386aac7ea9be44d23dcea28d9a02110c174e988Chris Banes } 2456386aac7ea9be44d23dcea28d9a02110c174e988Chris Banes 2466386aac7ea9be44d23dcea28d9a02110c174e988Chris Banes @Override 2476386aac7ea9be44d23dcea28d9a02110c174e988Chris Banes public void addContentView(View v, ViewGroup.LayoutParams lp) { 2486386aac7ea9be44d23dcea28d9a02110c174e988Chris Banes ensureSubDecor(); 24956fd50144df518461398a9b3397ee4842b346708Chris Banes ViewGroup contentParent = (ViewGroup) mActivity.findViewById(android.R.id.content); 25056fd50144df518461398a9b3397ee4842b346708Chris Banes contentParent.addView(v, lp); 251d64322f4b9686fabfd5a03f402d50a8e3fe5adedChris Banes mActivity.onSupportContentChanged(); 252d64322f4b9686fabfd5a03f402d50a8e3fe5adedChris Banes } 253d64322f4b9686fabfd5a03f402d50a8e3fe5adedChris Banes 254d64322f4b9686fabfd5a03f402d50a8e3fe5adedChris Banes @Override 255d64322f4b9686fabfd5a03f402d50a8e3fe5adedChris Banes public void onContentChanged() { 256d64322f4b9686fabfd5a03f402d50a8e3fe5adedChris Banes // Ignore all calls to this method as we call onSupportContentChanged manually above 2576386aac7ea9be44d23dcea28d9a02110c174e988Chris Banes } 2586386aac7ea9be44d23dcea28d9a02110c174e988Chris Banes 2598123e4b3d19031e34a60c0db202f0b3d100eb9d8Chris Banes final void ensureSubDecor() { 26056fd50144df518461398a9b3397ee4842b346708Chris Banes if (!mSubDecorInstalled) { 26156fd50144df518461398a9b3397ee4842b346708Chris Banes if (mHasActionBar) { 2624b217eaec19887b37d6d124df5ba04c5bb8b8141Chris Banes /** 2634b217eaec19887b37d6d124df5ba04c5bb8b8141Chris Banes * This needs some explanation. As we can not use the android:theme attribute 2644b217eaec19887b37d6d124df5ba04c5bb8b8141Chris Banes * pre-L, we emulate it by manually creating a LayoutInflater using a 2654b217eaec19887b37d6d124df5ba04c5bb8b8141Chris Banes * ContextThemeWrapper pointing to actionBarTheme. 2664b217eaec19887b37d6d124df5ba04c5bb8b8141Chris Banes */ 2674b217eaec19887b37d6d124df5ba04c5bb8b8141Chris Banes TypedValue outValue = new TypedValue(); 2684b217eaec19887b37d6d124df5ba04c5bb8b8141Chris Banes mActivity.getTheme().resolveAttribute(R.attr.actionBarTheme, outValue, true); 2694b217eaec19887b37d6d124df5ba04c5bb8b8141Chris Banes 2704b217eaec19887b37d6d124df5ba04c5bb8b8141Chris Banes Context themedContext; 2714b217eaec19887b37d6d124df5ba04c5bb8b8141Chris Banes if (outValue.resourceId != 0) { 2724b217eaec19887b37d6d124df5ba04c5bb8b8141Chris Banes themedContext = new ContextThemeWrapper(mActivity, outValue.resourceId); 2734b217eaec19887b37d6d124df5ba04c5bb8b8141Chris Banes } else { 2744b217eaec19887b37d6d124df5ba04c5bb8b8141Chris Banes themedContext = mActivity; 27561c0bbe56a13fe55ce91a5b1d64e751164ecb894Chris Banes } 27661c0bbe56a13fe55ce91a5b1d64e751164ecb894Chris Banes 2774b217eaec19887b37d6d124df5ba04c5bb8b8141Chris Banes // Now inflate the view using the themed context and set it as the content view 278ec3f49d21a507835c1f50ce5600000b587a2af08Chris Banes mSubDecor = (ViewGroup) LayoutInflater.from(themedContext) 2794b217eaec19887b37d6d124df5ba04c5bb8b8141Chris Banes .inflate(R.layout.abc_screen_toolbar, null); 2804b217eaec19887b37d6d124df5ba04c5bb8b8141Chris Banes 281ec3f49d21a507835c1f50ce5600000b587a2af08Chris Banes mDecorContentParent = (DecorContentParent) mSubDecor 28203fc11b659da1645507062bddda450136e13af35Chris Banes .findViewById(R.id.decor_content_parent); 283a6e86333cb4de18fc9b86746a49643e213db7c18Chris Banes mDecorContentParent.setWindowCallback(getWindowCallback()); 284ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes 28556fd50144df518461398a9b3397ee4842b346708Chris Banes /** 28649c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * Propagate features to DecorContentParent 28756fd50144df518461398a9b3397ee4842b346708Chris Banes */ 28849c78900da0d43140fb602431fb93212bd7f6c70Chris Banes if (mOverlayActionBar) { 289469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes mDecorContentParent.initFeature(FEATURE_ACTION_BAR_OVERLAY); 29049c78900da0d43140fb602431fb93212bd7f6c70Chris Banes } 29156fd50144df518461398a9b3397ee4842b346708Chris Banes if (mFeatureProgress) { 29249c78900da0d43140fb602431fb93212bd7f6c70Chris Banes mDecorContentParent.initFeature(Window.FEATURE_PROGRESS); 29356fd50144df518461398a9b3397ee4842b346708Chris Banes } 29456fd50144df518461398a9b3397ee4842b346708Chris Banes if (mFeatureIndeterminateProgress) { 29549c78900da0d43140fb602431fb93212bd7f6c70Chris Banes mDecorContentParent.initFeature(Window.FEATURE_INDETERMINATE_PROGRESS); 29656fd50144df518461398a9b3397ee4842b346708Chris Banes } 29756fd50144df518461398a9b3397ee4842b346708Chris Banes } else { 298ea4f700ac38424954c56df5138ff794def50b019Chris Banes if (mOverlayActionMode) { 299ea4f700ac38424954c56df5138ff794def50b019Chris Banes mSubDecor = (ViewGroup) LayoutInflater.from(mActivity) 300ea4f700ac38424954c56df5138ff794def50b019Chris Banes .inflate(R.layout.abc_screen_simple_overlay_action_mode, null); 301ea4f700ac38424954c56df5138ff794def50b019Chris Banes } else { 302ea4f700ac38424954c56df5138ff794def50b019Chris Banes mSubDecor = (ViewGroup) LayoutInflater.from(mActivity) 303ea4f700ac38424954c56df5138ff794def50b019Chris Banes .inflate(R.layout.abc_screen_simple, null); 304ea4f700ac38424954c56df5138ff794def50b019Chris Banes } 305ea4f700ac38424954c56df5138ff794def50b019Chris Banes 306ea4f700ac38424954c56df5138ff794def50b019Chris Banes if (Build.VERSION.SDK_INT >= 21) { 307ea4f700ac38424954c56df5138ff794def50b019Chris Banes // If we're running on L or above, we can rely on ViewCompat's 308ea4f700ac38424954c56df5138ff794def50b019Chris Banes // setOnApplyWindowInsetsListener 309ea4f700ac38424954c56df5138ff794def50b019Chris Banes ViewCompat.setOnApplyWindowInsetsListener(mSubDecor, 310ea4f700ac38424954c56df5138ff794def50b019Chris Banes new OnApplyWindowInsetsListener() { 311ea4f700ac38424954c56df5138ff794def50b019Chris Banes @Override 312ea4f700ac38424954c56df5138ff794def50b019Chris Banes public WindowInsetsCompat onApplyWindowInsets(View v, 313ea4f700ac38424954c56df5138ff794def50b019Chris Banes WindowInsetsCompat insets) { 314ea4f700ac38424954c56df5138ff794def50b019Chris Banes final int top = insets.getSystemWindowInsetTop(); 315ea4f700ac38424954c56df5138ff794def50b019Chris Banes final int newTop = updateStatusGuard(top); 316ea4f700ac38424954c56df5138ff794def50b019Chris Banes 317ea4f700ac38424954c56df5138ff794def50b019Chris Banes if (top != newTop) { 318ea4f700ac38424954c56df5138ff794def50b019Chris Banes return insets.replaceSystemWindowInsets( 319ea4f700ac38424954c56df5138ff794def50b019Chris Banes insets.getSystemWindowInsetLeft(), 320ea4f700ac38424954c56df5138ff794def50b019Chris Banes newTop, 321ea4f700ac38424954c56df5138ff794def50b019Chris Banes insets.getSystemWindowInsetRight(), 322ea4f700ac38424954c56df5138ff794def50b019Chris Banes insets.getSystemWindowInsetBottom()); 323ea4f700ac38424954c56df5138ff794def50b019Chris Banes } else { 324ea4f700ac38424954c56df5138ff794def50b019Chris Banes return insets; 325ea4f700ac38424954c56df5138ff794def50b019Chris Banes } 326ea4f700ac38424954c56df5138ff794def50b019Chris Banes } 327ea4f700ac38424954c56df5138ff794def50b019Chris Banes }); 328ea4f700ac38424954c56df5138ff794def50b019Chris Banes } else { 329ea4f700ac38424954c56df5138ff794def50b019Chris Banes // Else, we need to use our own FitWindowsViewGroup handling 330ea4f700ac38424954c56df5138ff794def50b019Chris Banes ((FitWindowsViewGroup) mSubDecor).setOnFitSystemWindowsListener( 331ea4f700ac38424954c56df5138ff794def50b019Chris Banes new FitWindowsViewGroup.OnFitSystemWindowsListener() { 332ea4f700ac38424954c56df5138ff794def50b019Chris Banes @Override 333ea4f700ac38424954c56df5138ff794def50b019Chris Banes public void onFitSystemWindows(Rect insets) { 334ea4f700ac38424954c56df5138ff794def50b019Chris Banes insets.top = updateStatusGuard(insets.top); 335ea4f700ac38424954c56df5138ff794def50b019Chris Banes } 336ea4f700ac38424954c56df5138ff794def50b019Chris Banes }); 337ea4f700ac38424954c56df5138ff794def50b019Chris Banes } 3383954d59cb6073615ead9dd34cbdba9e16b8c5b6fChris Banes } 3393954d59cb6073615ead9dd34cbdba9e16b8c5b6fChris Banes 3408c9ce11dec24a32f438406286404be7ac294011dChris Banes // The DecorView's original content view 3418c9ce11dec24a32f438406286404be7ac294011dChris Banes final View decorContent = mActivity.findViewById(android.R.id.content); 3428c9ce11dec24a32f438406286404be7ac294011dChris Banes 3438c9ce11dec24a32f438406286404be7ac294011dChris Banes // Traverse up the hierarchy from the original content view, making each view 3448c9ce11dec24a32f438406286404be7ac294011dChris Banes // ignore system window insets so that our sub-decor handles it 3458c9ce11dec24a32f438406286404be7ac294011dChris Banes View view = decorContent; 3468c9ce11dec24a32f438406286404be7ac294011dChris Banes while (view != mWindowDecor) { 3478c9ce11dec24a32f438406286404be7ac294011dChris Banes ViewCompat.setFitsSystemWindows(view, false); 3488c9ce11dec24a32f438406286404be7ac294011dChris Banes view = (View) view.getParent(); 3498c9ce11dec24a32f438406286404be7ac294011dChris Banes } 3508c9ce11dec24a32f438406286404be7ac294011dChris Banes 3511f4989216d62f70088cea29f9ae200a9bb3ff955Chris Banes // Make the decor optionally fit system windows, like the window's decor 352ec3f49d21a507835c1f50ce5600000b587a2af08Chris Banes ViewUtils.makeOptionalFitsSystemWindows(mSubDecor); 3531f4989216d62f70088cea29f9ae200a9bb3ff955Chris Banes 354ec3f49d21a507835c1f50ce5600000b587a2af08Chris Banes // Now set the Activity's content view with the decor 355ec3f49d21a507835c1f50ce5600000b587a2af08Chris Banes mActivity.superSetContentView(mSubDecor); 3561f4989216d62f70088cea29f9ae200a9bb3ff955Chris Banes 35792b18eb0263ef2421fda5bf977fea3bf044bf941Chris Banes // Change our content FrameLayout to use the android.R.id.content id. 35892b18eb0263ef2421fda5bf977fea3bf044bf941Chris Banes // Useful for fragments. 3594b217eaec19887b37d6d124df5ba04c5bb8b8141Chris Banes decorContent.setId(View.NO_ID); 36092b18eb0263ef2421fda5bf977fea3bf044bf941Chris Banes View abcContent = mActivity.findViewById(R.id.action_bar_activity_content); 36192b18eb0263ef2421fda5bf977fea3bf044bf941Chris Banes abcContent.setId(android.R.id.content); 36292b18eb0263ef2421fda5bf977fea3bf044bf941Chris Banes 3634b217eaec19887b37d6d124df5ba04c5bb8b8141Chris Banes // The decorContent may have a foreground drawable set (windowContentOverlay). 3644b217eaec19887b37d6d124df5ba04c5bb8b8141Chris Banes // Remove this as we handle it ourselves 3654b217eaec19887b37d6d124df5ba04c5bb8b8141Chris Banes if (decorContent instanceof FrameLayout) { 3664b217eaec19887b37d6d124df5ba04c5bb8b8141Chris Banes ((FrameLayout) decorContent).setForeground(null); 3674b217eaec19887b37d6d124df5ba04c5bb8b8141Chris Banes } 3684b217eaec19887b37d6d124df5ba04c5bb8b8141Chris Banes 369f53c7bf3146bf9bcba46324f9f06449df475be36Chris Banes // A title was set before we've install the decor so set it now. 37049c78900da0d43140fb602431fb93212bd7f6c70Chris Banes if (mTitleToSet != null && mDecorContentParent != null) { 37149c78900da0d43140fb602431fb93212bd7f6c70Chris Banes mDecorContentParent.setWindowTitle(mTitleToSet); 37256fd50144df518461398a9b3397ee4842b346708Chris Banes mTitleToSet = null; 373f53c7bf3146bf9bcba46324f9f06449df475be36Chris Banes } 374556ac47ce764a4a9320b5ac914536e9da2524176Chris Banes 37556fd50144df518461398a9b3397ee4842b346708Chris Banes applyFixedSizeWindow(); 37656fd50144df518461398a9b3397ee4842b346708Chris Banes 37749c78900da0d43140fb602431fb93212bd7f6c70Chris Banes onSubDecorInstalled(); 37849c78900da0d43140fb602431fb93212bd7f6c70Chris Banes 379f53c7bf3146bf9bcba46324f9f06449df475be36Chris Banes mSubDecorInstalled = true; 3808902df1bf0006a156503d40b1fc8a01f95d5b806Chris Banes 38100d183885b54de433e43118d3032340f40cac8c0Chris Banes // Invalidate if the panel menu hasn't been created before this. 38200d183885b54de433e43118d3032340f40cac8c0Chris Banes // Panel menu invalidation is deferred avoiding application onCreateOptionsMenu 38300d183885b54de433e43118d3032340f40cac8c0Chris Banes // being called in the middle of onCreate or similar. 38400d183885b54de433e43118d3032340f40cac8c0Chris Banes // A pending invalidation will typically be resolved before the posted message 38500d183885b54de433e43118d3032340f40cac8c0Chris Banes // would run normally in order to satisfy instance state restoration. 38600d183885b54de433e43118d3032340f40cac8c0Chris Banes PanelFeatureState st = getPanelState(FEATURE_OPTIONS_PANEL, false); 3879b1b5bfac6abfda6c7543fc1b57050649b04f41bChris Banes if (!isDestroyed() && (st == null || st.menu == null)) { 38800d183885b54de433e43118d3032340f40cac8c0Chris Banes invalidatePanelMenu(FEATURE_ACTION_BAR); 38900d183885b54de433e43118d3032340f40cac8c0Chris Banes } 3906386aac7ea9be44d23dcea28d9a02110c174e988Chris Banes } 3916386aac7ea9be44d23dcea28d9a02110c174e988Chris Banes } 3926386aac7ea9be44d23dcea28d9a02110c174e988Chris Banes 39349c78900da0d43140fb602431fb93212bd7f6c70Chris Banes void onSubDecorInstalled() {} 39449c78900da0d43140fb602431fb93212bd7f6c70Chris Banes 39556fd50144df518461398a9b3397ee4842b346708Chris Banes private void applyFixedSizeWindow() { 39649c78900da0d43140fb602431fb93212bd7f6c70Chris Banes TypedArray a = mActivity.obtainStyledAttributes(R.styleable.Theme); 39756fd50144df518461398a9b3397ee4842b346708Chris Banes 39856fd50144df518461398a9b3397ee4842b346708Chris Banes TypedValue mFixedWidthMajor = null; 39956fd50144df518461398a9b3397ee4842b346708Chris Banes TypedValue mFixedWidthMinor = null; 40056fd50144df518461398a9b3397ee4842b346708Chris Banes TypedValue mFixedHeightMajor = null; 40156fd50144df518461398a9b3397ee4842b346708Chris Banes TypedValue mFixedHeightMinor = null; 40256fd50144df518461398a9b3397ee4842b346708Chris Banes 40349c78900da0d43140fb602431fb93212bd7f6c70Chris Banes if (a.hasValue(R.styleable.Theme_windowFixedWidthMajor)) { 40456fd50144df518461398a9b3397ee4842b346708Chris Banes if (mFixedWidthMajor == null) mFixedWidthMajor = new TypedValue(); 40549c78900da0d43140fb602431fb93212bd7f6c70Chris Banes a.getValue(R.styleable.Theme_windowFixedWidthMajor, mFixedWidthMajor); 40656fd50144df518461398a9b3397ee4842b346708Chris Banes } 40749c78900da0d43140fb602431fb93212bd7f6c70Chris Banes if (a.hasValue(R.styleable.Theme_windowFixedWidthMinor)) { 40856fd50144df518461398a9b3397ee4842b346708Chris Banes if (mFixedWidthMinor == null) mFixedWidthMinor = new TypedValue(); 40949c78900da0d43140fb602431fb93212bd7f6c70Chris Banes a.getValue(R.styleable.Theme_windowFixedWidthMinor, mFixedWidthMinor); 41056fd50144df518461398a9b3397ee4842b346708Chris Banes } 41149c78900da0d43140fb602431fb93212bd7f6c70Chris Banes if (a.hasValue(R.styleable.Theme_windowFixedHeightMajor)) { 41256fd50144df518461398a9b3397ee4842b346708Chris Banes if (mFixedHeightMajor == null) mFixedHeightMajor = new TypedValue(); 41349c78900da0d43140fb602431fb93212bd7f6c70Chris Banes a.getValue(R.styleable.Theme_windowFixedHeightMajor, mFixedHeightMajor); 41456fd50144df518461398a9b3397ee4842b346708Chris Banes } 41549c78900da0d43140fb602431fb93212bd7f6c70Chris Banes if (a.hasValue(R.styleable.Theme_windowFixedHeightMinor)) { 41656fd50144df518461398a9b3397ee4842b346708Chris Banes if (mFixedHeightMinor == null) mFixedHeightMinor = new TypedValue(); 41749c78900da0d43140fb602431fb93212bd7f6c70Chris Banes a.getValue(R.styleable.Theme_windowFixedHeightMinor, mFixedHeightMinor); 41856fd50144df518461398a9b3397ee4842b346708Chris Banes } 41956fd50144df518461398a9b3397ee4842b346708Chris Banes 42056fd50144df518461398a9b3397ee4842b346708Chris Banes final DisplayMetrics metrics = mActivity.getResources().getDisplayMetrics(); 42156fd50144df518461398a9b3397ee4842b346708Chris Banes final boolean isPortrait = metrics.widthPixels < metrics.heightPixels; 42256fd50144df518461398a9b3397ee4842b346708Chris Banes int w = ViewGroup.LayoutParams.MATCH_PARENT; 42356fd50144df518461398a9b3397ee4842b346708Chris Banes int h = ViewGroup.LayoutParams.MATCH_PARENT; 42456fd50144df518461398a9b3397ee4842b346708Chris Banes 42556fd50144df518461398a9b3397ee4842b346708Chris Banes final TypedValue tvw = isPortrait ? mFixedWidthMinor : mFixedWidthMajor; 42656fd50144df518461398a9b3397ee4842b346708Chris Banes if (tvw != null && tvw.type != TypedValue.TYPE_NULL) { 42756fd50144df518461398a9b3397ee4842b346708Chris Banes if (tvw.type == TypedValue.TYPE_DIMENSION) { 42856fd50144df518461398a9b3397ee4842b346708Chris Banes w = (int) tvw.getDimension(metrics); 42956fd50144df518461398a9b3397ee4842b346708Chris Banes } else if (tvw.type == TypedValue.TYPE_FRACTION) { 43056fd50144df518461398a9b3397ee4842b346708Chris Banes w = (int) tvw.getFraction(metrics.widthPixels, metrics.widthPixels); 43156fd50144df518461398a9b3397ee4842b346708Chris Banes } 43256fd50144df518461398a9b3397ee4842b346708Chris Banes } 43356fd50144df518461398a9b3397ee4842b346708Chris Banes 43456fd50144df518461398a9b3397ee4842b346708Chris Banes final TypedValue tvh = isPortrait ? mFixedHeightMajor : mFixedHeightMinor; 43556fd50144df518461398a9b3397ee4842b346708Chris Banes if (tvh != null && tvh.type != TypedValue.TYPE_NULL) { 43656fd50144df518461398a9b3397ee4842b346708Chris Banes if (tvh.type == TypedValue.TYPE_DIMENSION) { 43756fd50144df518461398a9b3397ee4842b346708Chris Banes h = (int) tvh.getDimension(metrics); 43856fd50144df518461398a9b3397ee4842b346708Chris Banes } else if (tvh.type == TypedValue.TYPE_FRACTION) { 43956fd50144df518461398a9b3397ee4842b346708Chris Banes h = (int) tvh.getFraction(metrics.heightPixels, metrics.heightPixels); 44056fd50144df518461398a9b3397ee4842b346708Chris Banes } 44156fd50144df518461398a9b3397ee4842b346708Chris Banes } 44256fd50144df518461398a9b3397ee4842b346708Chris Banes 44356fd50144df518461398a9b3397ee4842b346708Chris Banes if (w != ViewGroup.LayoutParams.MATCH_PARENT || h != ViewGroup.LayoutParams.MATCH_PARENT) { 44456fd50144df518461398a9b3397ee4842b346708Chris Banes mActivity.getWindow().setLayout(w, h); 44556fd50144df518461398a9b3397ee4842b346708Chris Banes } 44656fd50144df518461398a9b3397ee4842b346708Chris Banes 44756fd50144df518461398a9b3397ee4842b346708Chris Banes a.recycle(); 44856fd50144df518461398a9b3397ee4842b346708Chris Banes } 44956fd50144df518461398a9b3397ee4842b346708Chris Banes 4506386aac7ea9be44d23dcea28d9a02110c174e988Chris Banes @Override 451ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes public boolean supportRequestWindowFeature(int featureId) { 4526386aac7ea9be44d23dcea28d9a02110c174e988Chris Banes switch (featureId) { 45300d183885b54de433e43118d3032340f40cac8c0Chris Banes case FEATURE_ACTION_BAR: 454cc7aada3ee922cfb38eeb36ee696cc73dcbae0a4Chris Banes throwFeatureRequestIfSubDecorInstalled(); 4555a2bcc375e046c5b6644dcc4d331d3fca0778aedChris Banes mHasActionBar = true; 4566386aac7ea9be44d23dcea28d9a02110c174e988Chris Banes return true; 45700d183885b54de433e43118d3032340f40cac8c0Chris Banes case FEATURE_ACTION_BAR_OVERLAY: 458cc7aada3ee922cfb38eeb36ee696cc73dcbae0a4Chris Banes throwFeatureRequestIfSubDecorInstalled(); 4595a2bcc375e046c5b6644dcc4d331d3fca0778aedChris Banes mOverlayActionBar = true; 4606386aac7ea9be44d23dcea28d9a02110c174e988Chris Banes return true; 46100d183885b54de433e43118d3032340f40cac8c0Chris Banes case FEATURE_ACTION_MODE_OVERLAY: 462cc7aada3ee922cfb38eeb36ee696cc73dcbae0a4Chris Banes throwFeatureRequestIfSubDecorInstalled(); 463de9f38cc4a30b33ac46b105edf470fbc4a044e99Chris Banes mOverlayActionMode = true; 464de9f38cc4a30b33ac46b105edf470fbc4a044e99Chris Banes return true; 465ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes case Window.FEATURE_PROGRESS: 466cc7aada3ee922cfb38eeb36ee696cc73dcbae0a4Chris Banes throwFeatureRequestIfSubDecorInstalled(); 467ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes mFeatureProgress = true; 468ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes return true; 469ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes case Window.FEATURE_INDETERMINATE_PROGRESS: 470cc7aada3ee922cfb38eeb36ee696cc73dcbae0a4Chris Banes throwFeatureRequestIfSubDecorInstalled(); 471ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes mFeatureIndeterminateProgress = true; 472ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes return true; 4736386aac7ea9be44d23dcea28d9a02110c174e988Chris Banes } 474cc7aada3ee922cfb38eeb36ee696cc73dcbae0a4Chris Banes 475cc7aada3ee922cfb38eeb36ee696cc73dcbae0a4Chris Banes return mActivity.requestWindowFeature(featureId); 4766386aac7ea9be44d23dcea28d9a02110c174e988Chris Banes } 4776386aac7ea9be44d23dcea28d9a02110c174e988Chris Banes 4786386aac7ea9be44d23dcea28d9a02110c174e988Chris Banes @Override 479904507029cd8ea2d070b6df0911b2dd36b7075a6Chris Banes public void onTitleChanged(CharSequence title) { 48049c78900da0d43140fb602431fb93212bd7f6c70Chris Banes if (mDecorContentParent != null) { 48149c78900da0d43140fb602431fb93212bd7f6c70Chris Banes mDecorContentParent.setWindowTitle(title); 48249c78900da0d43140fb602431fb93212bd7f6c70Chris Banes } else if (getSupportActionBar() != null) { 483ca58f2ce7cd9f0e0f2c4a46c3bcc98013209f6b3Chris Banes getSupportActionBar().setWindowTitle(title); 484f53c7bf3146bf9bcba46324f9f06449df475be36Chris Banes } else { 485f53c7bf3146bf9bcba46324f9f06449df475be36Chris Banes mTitleToSet = title; 4866386aac7ea9be44d23dcea28d9a02110c174e988Chris Banes } 4876386aac7ea9be44d23dcea28d9a02110c174e988Chris Banes } 4886386aac7ea9be44d23dcea28d9a02110c174e988Chris Banes 4896386aac7ea9be44d23dcea28d9a02110c174e988Chris Banes @Override 4906386aac7ea9be44d23dcea28d9a02110c174e988Chris Banes public View onCreatePanelView(int featureId) { 49157c6de90985a63358129b99b9f0cd4d6afe887d6Chris Banes View panelView = null; 49257c6de90985a63358129b99b9f0cd4d6afe887d6Chris Banes 49357c6de90985a63358129b99b9f0cd4d6afe887d6Chris Banes // If there isn't an action mode currently being displayed 49400d183885b54de433e43118d3032340f40cac8c0Chris Banes if (mActionMode == null) { 49557c6de90985a63358129b99b9f0cd4d6afe887d6Chris Banes // Let our window callback try first 49657c6de90985a63358129b99b9f0cd4d6afe887d6Chris Banes WindowCallback callback = getWindowCallback(); 49757c6de90985a63358129b99b9f0cd4d6afe887d6Chris Banes if (callback != null) { 49857c6de90985a63358129b99b9f0cd4d6afe887d6Chris Banes panelView = callback.onCreatePanelView(featureId); 49957c6de90985a63358129b99b9f0cd4d6afe887d6Chris Banes } 50057c6de90985a63358129b99b9f0cd4d6afe887d6Chris Banes 5010b7aedbbe43b9d4af60cc4ebd4994c74ebe6bc5fChris Banes if (panelView == null && mToolbarListMenuPresenter == null) { 5020b7aedbbe43b9d4af60cc4ebd4994c74ebe6bc5fChris Banes // Only check our panels if the callback didn't return a view and we do not have 5030b7aedbbe43b9d4af60cc4ebd4994c74ebe6bc5fChris Banes // a ListMenuPresenter for Toolbars. We check for the ListMenuPresenter because 5040b7aedbbe43b9d4af60cc4ebd4994c74ebe6bc5fChris Banes // once created, Toolbar needs to control the panel view regardless of whether it 5050b7aedbbe43b9d4af60cc4ebd4994c74ebe6bc5fChris Banes // has any non-action items to display. 50657c6de90985a63358129b99b9f0cd4d6afe887d6Chris Banes PanelFeatureState st = getPanelState(featureId, true); 50757c6de90985a63358129b99b9f0cd4d6afe887d6Chris Banes openPanel(st, null); 50857c6de90985a63358129b99b9f0cd4d6afe887d6Chris Banes if (st.isOpen) { 50957c6de90985a63358129b99b9f0cd4d6afe887d6Chris Banes panelView = st.shownPanelView; 51057c6de90985a63358129b99b9f0cd4d6afe887d6Chris Banes } 51157c6de90985a63358129b99b9f0cd4d6afe887d6Chris Banes } 5126386aac7ea9be44d23dcea28d9a02110c174e988Chris Banes } 51357c6de90985a63358129b99b9f0cd4d6afe887d6Chris Banes return panelView; 5146386aac7ea9be44d23dcea28d9a02110c174e988Chris Banes } 5156386aac7ea9be44d23dcea28d9a02110c174e988Chris Banes 5166386aac7ea9be44d23dcea28d9a02110c174e988Chris Banes @Override 51730837f1095c803f332f4a1c3f0917c8afdd50156Adam Powell public boolean onCreatePanelMenu(int featureId, Menu menu) { 51830837f1095c803f332f4a1c3f0917c8afdd50156Adam Powell if (featureId != Window.FEATURE_OPTIONS_PANEL) { 519a6e86333cb4de18fc9b86746a49643e213db7c18Chris Banes return getWindowCallback().onCreatePanelMenu(featureId, menu); 5206386aac7ea9be44d23dcea28d9a02110c174e988Chris Banes } 5216386aac7ea9be44d23dcea28d9a02110c174e988Chris Banes return false; 5226386aac7ea9be44d23dcea28d9a02110c174e988Chris Banes } 5236386aac7ea9be44d23dcea28d9a02110c174e988Chris Banes 5246386aac7ea9be44d23dcea28d9a02110c174e988Chris Banes @Override 52530837f1095c803f332f4a1c3f0917c8afdd50156Adam Powell public boolean onPreparePanel(int featureId, View view, Menu menu) { 52630837f1095c803f332f4a1c3f0917c8afdd50156Adam Powell if (featureId != Window.FEATURE_OPTIONS_PANEL) { 527a6e86333cb4de18fc9b86746a49643e213db7c18Chris Banes return getWindowCallback().onPreparePanel(featureId, view, menu); 5286386aac7ea9be44d23dcea28d9a02110c174e988Chris Banes } 5296386aac7ea9be44d23dcea28d9a02110c174e988Chris Banes return false; 5306386aac7ea9be44d23dcea28d9a02110c174e988Chris Banes } 5316386aac7ea9be44d23dcea28d9a02110c174e988Chris Banes 5326386aac7ea9be44d23dcea28d9a02110c174e988Chris Banes @Override 53300d183885b54de433e43118d3032340f40cac8c0Chris Banes public void onPanelClosed(final int featureId, Menu menu) { 53400d183885b54de433e43118d3032340f40cac8c0Chris Banes PanelFeatureState st = getPanelState(featureId, false); 53500d183885b54de433e43118d3032340f40cac8c0Chris Banes if (st != null) { 53600d183885b54de433e43118d3032340f40cac8c0Chris Banes // If we know about the feature id, update it's state 53700d183885b54de433e43118d3032340f40cac8c0Chris Banes closePanel(st, false); 53803fc11b659da1645507062bddda450136e13af35Chris Banes } 53900d183885b54de433e43118d3032340f40cac8c0Chris Banes 54000d183885b54de433e43118d3032340f40cac8c0Chris Banes if (featureId == FEATURE_ACTION_BAR) { 54100d183885b54de433e43118d3032340f40cac8c0Chris Banes ActionBar ab = getSupportActionBar(); 54200d183885b54de433e43118d3032340f40cac8c0Chris Banes if (ab != null) { 54300d183885b54de433e43118d3032340f40cac8c0Chris Banes ab.dispatchMenuVisibilityChanged(false); 54400d183885b54de433e43118d3032340f40cac8c0Chris Banes } 5459b1b5bfac6abfda6c7543fc1b57050649b04f41bChris Banes } else if (!isDestroyed()) { 54600d183885b54de433e43118d3032340f40cac8c0Chris Banes // Only pass it through to the Activity's super impl if it's not ACTION_BAR. This is 54700d183885b54de433e43118d3032340f40cac8c0Chris Banes // because ICS+ will try and create a framework action bar due to this call 548c4b9e0cb716a4caff218b27d86f37ef8117d257bChris Banes mActivity.superOnPanelClosed(featureId, menu); 549c4b9e0cb716a4caff218b27d86f37ef8117d257bChris Banes } 550c4b9e0cb716a4caff218b27d86f37ef8117d257bChris Banes } 551c4b9e0cb716a4caff218b27d86f37ef8117d257bChris Banes 552c4b9e0cb716a4caff218b27d86f37ef8117d257bChris Banes @Override 55300d183885b54de433e43118d3032340f40cac8c0Chris Banes boolean onMenuOpened(final int featureId, Menu menu) { 55400d183885b54de433e43118d3032340f40cac8c0Chris Banes if (featureId == FEATURE_ACTION_BAR) { 55500d183885b54de433e43118d3032340f40cac8c0Chris Banes ActionBar ab = getSupportActionBar(); 55600d183885b54de433e43118d3032340f40cac8c0Chris Banes if (ab != null) { 55700d183885b54de433e43118d3032340f40cac8c0Chris Banes ab.dispatchMenuVisibilityChanged(true); 55800d183885b54de433e43118d3032340f40cac8c0Chris Banes } 55900d183885b54de433e43118d3032340f40cac8c0Chris Banes return true; 56000d183885b54de433e43118d3032340f40cac8c0Chris Banes } else { 561c4b9e0cb716a4caff218b27d86f37ef8117d257bChris Banes return mActivity.superOnMenuOpened(featureId, menu); 562c4b9e0cb716a4caff218b27d86f37ef8117d257bChris Banes } 56303fc11b659da1645507062bddda450136e13af35Chris Banes } 56403fc11b659da1645507062bddda450136e13af35Chris Banes 56503fc11b659da1645507062bddda450136e13af35Chris Banes @Override 5666386aac7ea9be44d23dcea28d9a02110c174e988Chris Banes public boolean onMenuItemSelected(MenuBuilder menu, MenuItem item) { 5679b1b5bfac6abfda6c7543fc1b57050649b04f41bChris Banes final WindowCallback cb = getWindowCallback(); 5689b1b5bfac6abfda6c7543fc1b57050649b04f41bChris Banes if (cb != null && !isDestroyed()) { 5699b1b5bfac6abfda6c7543fc1b57050649b04f41bChris Banes final PanelFeatureState panel = findMenuPanel(menu.getRootMenu()); 5709b1b5bfac6abfda6c7543fc1b57050649b04f41bChris Banes if (panel != null) { 5719b1b5bfac6abfda6c7543fc1b57050649b04f41bChris Banes return cb.onMenuItemSelected(panel.featureId, item); 5729b1b5bfac6abfda6c7543fc1b57050649b04f41bChris Banes } 5739b1b5bfac6abfda6c7543fc1b57050649b04f41bChris Banes } 5749b1b5bfac6abfda6c7543fc1b57050649b04f41bChris Banes return false; 5756386aac7ea9be44d23dcea28d9a02110c174e988Chris Banes } 5766386aac7ea9be44d23dcea28d9a02110c174e988Chris Banes 5776386aac7ea9be44d23dcea28d9a02110c174e988Chris Banes @Override 5786386aac7ea9be44d23dcea28d9a02110c174e988Chris Banes public void onMenuModeChange(MenuBuilder menu) { 5796386aac7ea9be44d23dcea28d9a02110c174e988Chris Banes reopenMenu(menu, true); 5806386aac7ea9be44d23dcea28d9a02110c174e988Chris Banes } 5816386aac7ea9be44d23dcea28d9a02110c174e988Chris Banes 5826386aac7ea9be44d23dcea28d9a02110c174e988Chris Banes @Override 583d8222dedaacae30fa03bee346ebf42ee75b39928Chris Banes public ActionMode startSupportActionMode(ActionMode.Callback callback) { 584d8222dedaacae30fa03bee346ebf42ee75b39928Chris Banes if (callback == null) { 585d8222dedaacae30fa03bee346ebf42ee75b39928Chris Banes throw new IllegalArgumentException("ActionMode callback can not be null."); 586d8222dedaacae30fa03bee346ebf42ee75b39928Chris Banes } 587d8222dedaacae30fa03bee346ebf42ee75b39928Chris Banes 588d8222dedaacae30fa03bee346ebf42ee75b39928Chris Banes if (mActionMode != null) { 589d8222dedaacae30fa03bee346ebf42ee75b39928Chris Banes mActionMode.finish(); 590d8222dedaacae30fa03bee346ebf42ee75b39928Chris Banes } 591d8222dedaacae30fa03bee346ebf42ee75b39928Chris Banes 592d8222dedaacae30fa03bee346ebf42ee75b39928Chris Banes final ActionMode.Callback wrappedCallback = new ActionModeCallbackWrapper(callback); 593d8222dedaacae30fa03bee346ebf42ee75b39928Chris Banes 59449c78900da0d43140fb602431fb93212bd7f6c70Chris Banes ActionBar ab = getSupportActionBar(); 595d8222dedaacae30fa03bee346ebf42ee75b39928Chris Banes if (ab != null) { 5965a2bcc375e046c5b6644dcc4d331d3fca0778aedChris Banes mActionMode = ab.startActionMode(wrappedCallback); 5970bf48858279237f95d6aad565a074490745491cdChris Banes if (mActionMode != null) { 5980bf48858279237f95d6aad565a074490745491cdChris Banes mActivity.onSupportActionModeStarted(mActionMode); 5990bf48858279237f95d6aad565a074490745491cdChris Banes } 600d8222dedaacae30fa03bee346ebf42ee75b39928Chris Banes } 601d8222dedaacae30fa03bee346ebf42ee75b39928Chris Banes 6020bf48858279237f95d6aad565a074490745491cdChris Banes if (mActionMode == null) { 6030bf48858279237f95d6aad565a074490745491cdChris Banes // If the action bar didn't provide an action mode, start the emulated window one 6040bf48858279237f95d6aad565a074490745491cdChris Banes mActionMode = startSupportActionModeFromWindow(wrappedCallback); 605d8222dedaacae30fa03bee346ebf42ee75b39928Chris Banes } 6060bf48858279237f95d6aad565a074490745491cdChris Banes 607d8222dedaacae30fa03bee346ebf42ee75b39928Chris Banes return mActionMode; 608d8222dedaacae30fa03bee346ebf42ee75b39928Chris Banes } 609d8222dedaacae30fa03bee346ebf42ee75b39928Chris Banes 610d8222dedaacae30fa03bee346ebf42ee75b39928Chris Banes @Override 6116386aac7ea9be44d23dcea28d9a02110c174e988Chris Banes public void supportInvalidateOptionsMenu() { 612f2045f06bdfc9e2cc40a734e41e45d11adf2bc23Chris Banes final ActionBar ab = getSupportActionBar(); 613f2045f06bdfc9e2cc40a734e41e45d11adf2bc23Chris Banes if (ab != null && ab.invalidateOptionsMenu()) return; 614f2045f06bdfc9e2cc40a734e41e45d11adf2bc23Chris Banes 61500d183885b54de433e43118d3032340f40cac8c0Chris Banes invalidatePanelMenu(FEATURE_OPTIONS_PANEL); 6166386aac7ea9be44d23dcea28d9a02110c174e988Chris Banes } 6176386aac7ea9be44d23dcea28d9a02110c174e988Chris Banes 6184c2a95906254748cb9a843b061288265d6e185a9Chris Banes @Override 6194c2a95906254748cb9a843b061288265d6e185a9Chris Banes ActionMode startSupportActionModeFromWindow(ActionMode.Callback callback) { 6204c2a95906254748cb9a843b061288265d6e185a9Chris Banes if (mActionMode != null) { 6214c2a95906254748cb9a843b061288265d6e185a9Chris Banes mActionMode.finish(); 6224c2a95906254748cb9a843b061288265d6e185a9Chris Banes } 6234c2a95906254748cb9a843b061288265d6e185a9Chris Banes 6244c2a95906254748cb9a843b061288265d6e185a9Chris Banes final ActionMode.Callback wrappedCallback = new ActionModeCallbackWrapper(callback); 6254bd5cbd6ca4f1e5ed43217b808068a48f937feabChris Banes final Context context = getActionBarThemedContext(); 6264c2a95906254748cb9a843b061288265d6e185a9Chris Banes 6274c2a95906254748cb9a843b061288265d6e185a9Chris Banes if (mActionModeView == null) { 6284c2a95906254748cb9a843b061288265d6e185a9Chris Banes if (mIsFloating) { 6294bd5cbd6ca4f1e5ed43217b808068a48f937feabChris Banes mActionModeView = new ActionBarContextView(context); 6304bd5cbd6ca4f1e5ed43217b808068a48f937feabChris Banes mActionModePopup = new PopupWindow(context, null, 6314c2a95906254748cb9a843b061288265d6e185a9Chris Banes R.attr.actionModePopupWindowStyle); 6324c2a95906254748cb9a843b061288265d6e185a9Chris Banes mActionModePopup.setContentView(mActionModeView); 6334c2a95906254748cb9a843b061288265d6e185a9Chris Banes mActionModePopup.setWidth(ViewGroup.LayoutParams.MATCH_PARENT); 6344c2a95906254748cb9a843b061288265d6e185a9Chris Banes 6354c2a95906254748cb9a843b061288265d6e185a9Chris Banes TypedValue heightValue = new TypedValue(); 6364c2a95906254748cb9a843b061288265d6e185a9Chris Banes mActivity.getTheme().resolveAttribute(R.attr.actionBarSize, heightValue, true); 6374c2a95906254748cb9a843b061288265d6e185a9Chris Banes final int height = TypedValue.complexToDimensionPixelSize(heightValue.data, 6384c2a95906254748cb9a843b061288265d6e185a9Chris Banes mActivity.getResources().getDisplayMetrics()); 6394c2a95906254748cb9a843b061288265d6e185a9Chris Banes mActionModeView.setContentHeight(height); 6404c2a95906254748cb9a843b061288265d6e185a9Chris Banes mActionModePopup.setHeight(ViewGroup.LayoutParams.WRAP_CONTENT); 6414c2a95906254748cb9a843b061288265d6e185a9Chris Banes mShowActionModePopup = new Runnable() { 6424c2a95906254748cb9a843b061288265d6e185a9Chris Banes public void run() { 6434c2a95906254748cb9a843b061288265d6e185a9Chris Banes mActionModePopup.showAtLocation( 6444c2a95906254748cb9a843b061288265d6e185a9Chris Banes mActionModeView, 6454c2a95906254748cb9a843b061288265d6e185a9Chris Banes Gravity.TOP | Gravity.FILL_HORIZONTAL, 0, 0); 6464c2a95906254748cb9a843b061288265d6e185a9Chris Banes } 6474c2a95906254748cb9a843b061288265d6e185a9Chris Banes }; 6484c2a95906254748cb9a843b061288265d6e185a9Chris Banes } else { 6494bd5cbd6ca4f1e5ed43217b808068a48f937feabChris Banes ViewStubCompat stub = (ViewStubCompat) mActivity 6504bd5cbd6ca4f1e5ed43217b808068a48f937feabChris Banes .findViewById(R.id.action_mode_bar_stub); 6514c2a95906254748cb9a843b061288265d6e185a9Chris Banes if (stub != null) { 6524bd5cbd6ca4f1e5ed43217b808068a48f937feabChris Banes // Set the layout inflater so that it is inflated with the action bar's context 6534bd5cbd6ca4f1e5ed43217b808068a48f937feabChris Banes stub.setLayoutInflater(LayoutInflater.from(context)); 6544c2a95906254748cb9a843b061288265d6e185a9Chris Banes mActionModeView = (ActionBarContextView) stub.inflate(); 6554c2a95906254748cb9a843b061288265d6e185a9Chris Banes } 6564c2a95906254748cb9a843b061288265d6e185a9Chris Banes } 6574c2a95906254748cb9a843b061288265d6e185a9Chris Banes } 6584c2a95906254748cb9a843b061288265d6e185a9Chris Banes 6594c2a95906254748cb9a843b061288265d6e185a9Chris Banes if (mActionModeView != null) { 6604c2a95906254748cb9a843b061288265d6e185a9Chris Banes mActionModeView.killMode(); 6614bd5cbd6ca4f1e5ed43217b808068a48f937feabChris Banes ActionMode mode = new StandaloneActionMode(context, mActionModeView, wrappedCallback, 6624c2a95906254748cb9a843b061288265d6e185a9Chris Banes mActionModePopup == null); 6634c2a95906254748cb9a843b061288265d6e185a9Chris Banes if (callback.onCreateActionMode(mode, mode.getMenu())) { 6644c2a95906254748cb9a843b061288265d6e185a9Chris Banes mode.invalidate(); 6654c2a95906254748cb9a843b061288265d6e185a9Chris Banes mActionModeView.initForMode(mode); 6664c2a95906254748cb9a843b061288265d6e185a9Chris Banes mActionModeView.setVisibility(View.VISIBLE); 6674c2a95906254748cb9a843b061288265d6e185a9Chris Banes mActionMode = mode; 6684c2a95906254748cb9a843b061288265d6e185a9Chris Banes if (mActionModePopup != null) { 6694c2a95906254748cb9a843b061288265d6e185a9Chris Banes mActivity.getWindow().getDecorView().post(mShowActionModePopup); 6704c2a95906254748cb9a843b061288265d6e185a9Chris Banes } 6714c2a95906254748cb9a843b061288265d6e185a9Chris Banes mActionModeView.sendAccessibilityEvent( 6724c2a95906254748cb9a843b061288265d6e185a9Chris Banes AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED); 673ec3f49d21a507835c1f50ce5600000b587a2af08Chris Banes 674ec3f49d21a507835c1f50ce5600000b587a2af08Chris Banes if (mActionModeView.getParent() != null) { 675ec3f49d21a507835c1f50ce5600000b587a2af08Chris Banes ViewCompat.requestApplyInsets((View) mActionModeView.getParent()); 676ec3f49d21a507835c1f50ce5600000b587a2af08Chris Banes } 6774c2a95906254748cb9a843b061288265d6e185a9Chris Banes } else { 6784c2a95906254748cb9a843b061288265d6e185a9Chris Banes mActionMode = null; 6794c2a95906254748cb9a843b061288265d6e185a9Chris Banes } 6804c2a95906254748cb9a843b061288265d6e185a9Chris Banes } 6814c2a95906254748cb9a843b061288265d6e185a9Chris Banes if (mActionMode != null && mActivity != null) { 6824c2a95906254748cb9a843b061288265d6e185a9Chris Banes mActivity.onSupportActionModeStarted(mActionMode); 6834c2a95906254748cb9a843b061288265d6e185a9Chris Banes } 6844c2a95906254748cb9a843b061288265d6e185a9Chris Banes return mActionMode; 6854c2a95906254748cb9a843b061288265d6e185a9Chris Banes } 6864c2a95906254748cb9a843b061288265d6e185a9Chris Banes 687d8222dedaacae30fa03bee346ebf42ee75b39928Chris Banes @Override 688d8222dedaacae30fa03bee346ebf42ee75b39928Chris Banes public boolean onBackPressed() { 689d8222dedaacae30fa03bee346ebf42ee75b39928Chris Banes // Back cancels action modes first. 690d8222dedaacae30fa03bee346ebf42ee75b39928Chris Banes if (mActionMode != null) { 691d8222dedaacae30fa03bee346ebf42ee75b39928Chris Banes mActionMode.finish(); 692d8222dedaacae30fa03bee346ebf42ee75b39928Chris Banes return true; 693d8222dedaacae30fa03bee346ebf42ee75b39928Chris Banes } 694d8222dedaacae30fa03bee346ebf42ee75b39928Chris Banes 695d8222dedaacae30fa03bee346ebf42ee75b39928Chris Banes // Next collapse any expanded action views. 69649c78900da0d43140fb602431fb93212bd7f6c70Chris Banes ActionBar ab = getSupportActionBar(); 69749c78900da0d43140fb602431fb93212bd7f6c70Chris Banes if (ab != null && ab.collapseActionView()) { 698d8222dedaacae30fa03bee346ebf42ee75b39928Chris Banes return true; 699d8222dedaacae30fa03bee346ebf42ee75b39928Chris Banes } 700d8222dedaacae30fa03bee346ebf42ee75b39928Chris Banes 701d8222dedaacae30fa03bee346ebf42ee75b39928Chris Banes return false; 702d8222dedaacae30fa03bee346ebf42ee75b39928Chris Banes } 703d8222dedaacae30fa03bee346ebf42ee75b39928Chris Banes 704d8222dedaacae30fa03bee346ebf42ee75b39928Chris Banes @Override 705ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes void setSupportProgressBarVisibility(boolean visible) { 706c132781c9ed6354e451c647737013600b0da2425Chris Banes // noop 707ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes } 708ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes 709ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes @Override 710ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes void setSupportProgressBarIndeterminateVisibility(boolean visible) { 711c132781c9ed6354e451c647737013600b0da2425Chris Banes // noop 712ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes } 713ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes 714ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes @Override 715ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes void setSupportProgressBarIndeterminate(boolean indeterminate) { 716c132781c9ed6354e451c647737013600b0da2425Chris Banes // noop 717ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes } 718ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes 719ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes @Override 720ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes void setSupportProgress(int progress) { 721c132781c9ed6354e451c647737013600b0da2425Chris Banes // noop 722ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes } 723ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes 72445d973fcc4c43f5ea00cddd3d9b947d9e8d8fc4eChris Banes @Override 725f4a93d160fc696de65e103e7e078106ea8f818faChris Banes int getHomeAsUpIndicatorAttrId() { 726f4a93d160fc696de65e103e7e078106ea8f818faChris Banes return R.attr.homeAsUpIndicator; 72745d973fcc4c43f5ea00cddd3d9b947d9e8d8fc4eChris Banes } 72845d973fcc4c43f5ea00cddd3d9b947d9e8d8fc4eChris Banes 729dea1122145ed85590d298a3a9d88ba9f9e2f5f46Chris Banes @Override 73000d183885b54de433e43118d3032340f40cac8c0Chris Banes boolean onKeyShortcut(int keyCode, KeyEvent ev) { 731d15ee7df01f2f48b536a610c4739f33b226d3f81Chris Banes // Let the Action Bar have a chance at handling the shortcut 732d15ee7df01f2f48b536a610c4739f33b226d3f81Chris Banes ActionBar ab = getSupportActionBar(); 733d15ee7df01f2f48b536a610c4739f33b226d3f81Chris Banes if (ab != null && ab.onKeyShortcut(keyCode, ev)) { 734d15ee7df01f2f48b536a610c4739f33b226d3f81Chris Banes return true; 735d15ee7df01f2f48b536a610c4739f33b226d3f81Chris Banes } 736d15ee7df01f2f48b536a610c4739f33b226d3f81Chris Banes 737dea1122145ed85590d298a3a9d88ba9f9e2f5f46Chris Banes // If the panel is already prepared, then perform the shortcut using it. 73800d183885b54de433e43118d3032340f40cac8c0Chris Banes boolean handled; 73900d183885b54de433e43118d3032340f40cac8c0Chris Banes if (mPreparedPanel != null) { 74000d183885b54de433e43118d3032340f40cac8c0Chris Banes handled = performPanelShortcut(mPreparedPanel, ev.getKeyCode(), ev, 74100d183885b54de433e43118d3032340f40cac8c0Chris Banes Menu.FLAG_PERFORM_NO_CLOSE); 74200d183885b54de433e43118d3032340f40cac8c0Chris Banes if (handled) { 74300d183885b54de433e43118d3032340f40cac8c0Chris Banes if (mPreparedPanel != null) { 74400d183885b54de433e43118d3032340f40cac8c0Chris Banes mPreparedPanel.isHandled = true; 74500d183885b54de433e43118d3032340f40cac8c0Chris Banes } 74600d183885b54de433e43118d3032340f40cac8c0Chris Banes return true; 74700d183885b54de433e43118d3032340f40cac8c0Chris Banes } 74800d183885b54de433e43118d3032340f40cac8c0Chris Banes } 74900d183885b54de433e43118d3032340f40cac8c0Chris Banes 75000d183885b54de433e43118d3032340f40cac8c0Chris Banes // If the panel is not prepared, then we may be trying to handle a shortcut key 75100d183885b54de433e43118d3032340f40cac8c0Chris Banes // combination such as Control+C. Temporarily prepare the panel then mark it 75200d183885b54de433e43118d3032340f40cac8c0Chris Banes // unprepared again when finished to ensure that the panel will again be prepared 75300d183885b54de433e43118d3032340f40cac8c0Chris Banes // the next time it is shown for real. 75400d183885b54de433e43118d3032340f40cac8c0Chris Banes if (mPreparedPanel == null) { 75500d183885b54de433e43118d3032340f40cac8c0Chris Banes PanelFeatureState st = getPanelState(FEATURE_OPTIONS_PANEL, true); 75600d183885b54de433e43118d3032340f40cac8c0Chris Banes preparePanel(st, ev); 75700d183885b54de433e43118d3032340f40cac8c0Chris Banes handled = performPanelShortcut(st, ev.getKeyCode(), ev, Menu.FLAG_PERFORM_NO_CLOSE); 75800d183885b54de433e43118d3032340f40cac8c0Chris Banes st.isPrepared = false; 75900d183885b54de433e43118d3032340f40cac8c0Chris Banes if (handled) { 76000d183885b54de433e43118d3032340f40cac8c0Chris Banes return true; 76100d183885b54de433e43118d3032340f40cac8c0Chris Banes } 76200d183885b54de433e43118d3032340f40cac8c0Chris Banes } 76300d183885b54de433e43118d3032340f40cac8c0Chris Banes return false; 764dea1122145ed85590d298a3a9d88ba9f9e2f5f46Chris Banes } 765dea1122145ed85590d298a3a9d88ba9f9e2f5f46Chris Banes 766dea1122145ed85590d298a3a9d88ba9f9e2f5f46Chris Banes @Override 767dea1122145ed85590d298a3a9d88ba9f9e2f5f46Chris Banes boolean onKeyDown(int keyCode, KeyEvent event) { 768dea1122145ed85590d298a3a9d88ba9f9e2f5f46Chris Banes // On API v7-10 we need to manually call onKeyShortcut() as this is not called 769dea1122145ed85590d298a3a9d88ba9f9e2f5f46Chris Banes // from the Activity 770dea1122145ed85590d298a3a9d88ba9f9e2f5f46Chris Banes return onKeyShortcut(keyCode, event); 771dea1122145ed85590d298a3a9d88ba9f9e2f5f46Chris Banes } 772dea1122145ed85590d298a3a9d88ba9f9e2f5f46Chris Banes 773469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes @Override 7741c7a431337d8794b8c72291a281d7ebed0d2b397Chris Banes View createView(final String name, @NonNull Context context, @NonNull AttributeSet attrs) { 775469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes if (Build.VERSION.SDK_INT < 21) { 776469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes // If we're running pre-L, we need to 'inject' our tint aware Views in place of the 777469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes // standard framework versions 778469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes switch (name) { 779469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes case "EditText": 7801c7a431337d8794b8c72291a281d7ebed0d2b397Chris Banes return new TintEditText(context, attrs); 781415f740df4981ef2f5fb462a50c7cf095cc21128Chris Banes case "Spinner": 7821c7a431337d8794b8c72291a281d7ebed0d2b397Chris Banes return new TintSpinner(context, attrs); 783415f740df4981ef2f5fb462a50c7cf095cc21128Chris Banes case "CheckBox": 7841c7a431337d8794b8c72291a281d7ebed0d2b397Chris Banes return new TintCheckBox(context, attrs); 785415f740df4981ef2f5fb462a50c7cf095cc21128Chris Banes case "RadioButton": 7861c7a431337d8794b8c72291a281d7ebed0d2b397Chris Banes return new TintRadioButton(context, attrs); 787415f740df4981ef2f5fb462a50c7cf095cc21128Chris Banes case "CheckedTextView": 7881c7a431337d8794b8c72291a281d7ebed0d2b397Chris Banes return new TintCheckedTextView(context, attrs); 789012047c60d03e61498955b7fa3e9cb9b409fbad8Chris Banes case "AutoCompleteTextView": 7901c7a431337d8794b8c72291a281d7ebed0d2b397Chris Banes return new TintAutoCompleteTextView(context, attrs); 791012047c60d03e61498955b7fa3e9cb9b409fbad8Chris Banes case "MultiAutoCompleteTextView": 7921c7a431337d8794b8c72291a281d7ebed0d2b397Chris Banes return new TintMultiAutoCompleteTextView(context, attrs); 793a9585dae398a69dd67797e7ca86f44ffcabd9e86Chris Banes case "RatingBar": 794a9585dae398a69dd67797e7ca86f44ffcabd9e86Chris Banes return new TintRatingBar(context, attrs); 795a9585dae398a69dd67797e7ca86f44ffcabd9e86Chris Banes case "Button": 796a9585dae398a69dd67797e7ca86f44ffcabd9e86Chris Banes return new TintButton(context, attrs); 797469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes } 798469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes } 799469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes return null; 800469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes } 801469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes 80200d183885b54de433e43118d3032340f40cac8c0Chris Banes private void openPanel(int featureId, KeyEvent event) { 80300d183885b54de433e43118d3032340f40cac8c0Chris Banes if (featureId == FEATURE_OPTIONS_PANEL && mDecorContentParent != null && 80400d183885b54de433e43118d3032340f40cac8c0Chris Banes mDecorContentParent.canShowOverflowMenu() && 80500d183885b54de433e43118d3032340f40cac8c0Chris Banes !ViewConfigurationCompat.hasPermanentMenuKey(ViewConfiguration.get(mActivity))) { 80600d183885b54de433e43118d3032340f40cac8c0Chris Banes mDecorContentParent.showOverflowMenu(); 80700d183885b54de433e43118d3032340f40cac8c0Chris Banes } else { 80800d183885b54de433e43118d3032340f40cac8c0Chris Banes openPanel(getPanelState(featureId, true), event); 80900d183885b54de433e43118d3032340f40cac8c0Chris Banes } 81000d183885b54de433e43118d3032340f40cac8c0Chris Banes } 81100d183885b54de433e43118d3032340f40cac8c0Chris Banes 81200d183885b54de433e43118d3032340f40cac8c0Chris Banes private void openPanel(final PanelFeatureState st, KeyEvent event) { 81300d183885b54de433e43118d3032340f40cac8c0Chris Banes // Already open, return 8149b1b5bfac6abfda6c7543fc1b57050649b04f41bChris Banes if (st.isOpen || isDestroyed()) { 81500d183885b54de433e43118d3032340f40cac8c0Chris Banes return; 81600d183885b54de433e43118d3032340f40cac8c0Chris Banes } 81700d183885b54de433e43118d3032340f40cac8c0Chris Banes 81800d183885b54de433e43118d3032340f40cac8c0Chris Banes // Don't open an options panel for honeycomb apps on xlarge devices. 81900d183885b54de433e43118d3032340f40cac8c0Chris Banes // (The app should be using an action bar for menu items.) 82000d183885b54de433e43118d3032340f40cac8c0Chris Banes if (st.featureId == FEATURE_OPTIONS_PANEL) { 82100d183885b54de433e43118d3032340f40cac8c0Chris Banes Context context = mActivity; 82200d183885b54de433e43118d3032340f40cac8c0Chris Banes Configuration config = context.getResources().getConfiguration(); 82300d183885b54de433e43118d3032340f40cac8c0Chris Banes boolean isXLarge = (config.screenLayout & Configuration.SCREENLAYOUT_SIZE_MASK) == 82400d183885b54de433e43118d3032340f40cac8c0Chris Banes Configuration.SCREENLAYOUT_SIZE_XLARGE; 82500d183885b54de433e43118d3032340f40cac8c0Chris Banes boolean isHoneycombApp = context.getApplicationInfo().targetSdkVersion >= 82600d183885b54de433e43118d3032340f40cac8c0Chris Banes android.os.Build.VERSION_CODES.HONEYCOMB; 82700d183885b54de433e43118d3032340f40cac8c0Chris Banes 82800d183885b54de433e43118d3032340f40cac8c0Chris Banes if (isXLarge && isHoneycombApp) { 82900d183885b54de433e43118d3032340f40cac8c0Chris Banes return; 83000d183885b54de433e43118d3032340f40cac8c0Chris Banes } 83100d183885b54de433e43118d3032340f40cac8c0Chris Banes } 83200d183885b54de433e43118d3032340f40cac8c0Chris Banes 83300d183885b54de433e43118d3032340f40cac8c0Chris Banes WindowCallback cb = getWindowCallback(); 83400d183885b54de433e43118d3032340f40cac8c0Chris Banes if ((cb != null) && (!cb.onMenuOpened(st.featureId, st.menu))) { 83500d183885b54de433e43118d3032340f40cac8c0Chris Banes // Callback doesn't want the menu to open, reset any state 83600d183885b54de433e43118d3032340f40cac8c0Chris Banes closePanel(st, true); 83700d183885b54de433e43118d3032340f40cac8c0Chris Banes return; 83800d183885b54de433e43118d3032340f40cac8c0Chris Banes } 83900d183885b54de433e43118d3032340f40cac8c0Chris Banes 84000d183885b54de433e43118d3032340f40cac8c0Chris Banes // Prepare panel (should have been done before, but just in case) 84100d183885b54de433e43118d3032340f40cac8c0Chris Banes if (!preparePanel(st, event)) { 84200d183885b54de433e43118d3032340f40cac8c0Chris Banes return; 84300d183885b54de433e43118d3032340f40cac8c0Chris Banes } 84400d183885b54de433e43118d3032340f40cac8c0Chris Banes 84500d183885b54de433e43118d3032340f40cac8c0Chris Banes if (st.decorView == null || st.refreshDecorView) { 84600d183885b54de433e43118d3032340f40cac8c0Chris Banes initializePanelDecor(st); 84700d183885b54de433e43118d3032340f40cac8c0Chris Banes } 84800d183885b54de433e43118d3032340f40cac8c0Chris Banes 84900d183885b54de433e43118d3032340f40cac8c0Chris Banes // This will populate st.shownPanelView 85000d183885b54de433e43118d3032340f40cac8c0Chris Banes if (!initializePanelContent(st) || !st.hasPanelItems()) { 85100d183885b54de433e43118d3032340f40cac8c0Chris Banes return; 85200d183885b54de433e43118d3032340f40cac8c0Chris Banes } 85300d183885b54de433e43118d3032340f40cac8c0Chris Banes 85400d183885b54de433e43118d3032340f40cac8c0Chris Banes st.isHandled = false; 85500d183885b54de433e43118d3032340f40cac8c0Chris Banes st.isOpen = true; 85600d183885b54de433e43118d3032340f40cac8c0Chris Banes } 85700d183885b54de433e43118d3032340f40cac8c0Chris Banes 85800d183885b54de433e43118d3032340f40cac8c0Chris Banes private void initializePanelDecor(PanelFeatureState st) { 85900d183885b54de433e43118d3032340f40cac8c0Chris Banes st.decorView = mWindowDecor; 86057c6de90985a63358129b99b9f0cd4d6afe887d6Chris Banes st.setStyle(getActionBarThemedContext()); 86100d183885b54de433e43118d3032340f40cac8c0Chris Banes } 86200d183885b54de433e43118d3032340f40cac8c0Chris Banes 86300d183885b54de433e43118d3032340f40cac8c0Chris Banes private void reopenMenu(MenuBuilder menu, boolean toggleMenuMode) { 86400d183885b54de433e43118d3032340f40cac8c0Chris Banes if (mDecorContentParent != null && mDecorContentParent.canShowOverflowMenu() && 86500d183885b54de433e43118d3032340f40cac8c0Chris Banes (!ViewConfigurationCompat.hasPermanentMenuKey(ViewConfiguration.get(mActivity)) || 86600d183885b54de433e43118d3032340f40cac8c0Chris Banes mDecorContentParent.isOverflowMenuShowPending())) { 8679b1b5bfac6abfda6c7543fc1b57050649b04f41bChris Banes 8689b1b5bfac6abfda6c7543fc1b57050649b04f41bChris Banes WindowCallback cb = getWindowCallback(); 8699b1b5bfac6abfda6c7543fc1b57050649b04f41bChris Banes 87000d183885b54de433e43118d3032340f40cac8c0Chris Banes if (!mDecorContentParent.isOverflowMenuShowing() || !toggleMenuMode) { 8719b1b5bfac6abfda6c7543fc1b57050649b04f41bChris Banes if (cb != null && !isDestroyed()) { 8729b1b5bfac6abfda6c7543fc1b57050649b04f41bChris Banes // If we have a menu invalidation pending, do it now. 8739b1b5bfac6abfda6c7543fc1b57050649b04f41bChris Banes if (mInvalidatePanelMenuPosted && 8749b1b5bfac6abfda6c7543fc1b57050649b04f41bChris Banes (mInvalidatePanelMenuFeatures & (1 << FEATURE_OPTIONS_PANEL)) != 0) { 8759b1b5bfac6abfda6c7543fc1b57050649b04f41bChris Banes mWindowDecor.removeCallbacks(mInvalidatePanelMenuRunnable); 8769b1b5bfac6abfda6c7543fc1b57050649b04f41bChris Banes mInvalidatePanelMenuRunnable.run(); 8779b1b5bfac6abfda6c7543fc1b57050649b04f41bChris Banes } 87800d183885b54de433e43118d3032340f40cac8c0Chris Banes 8799b1b5bfac6abfda6c7543fc1b57050649b04f41bChris Banes final PanelFeatureState st = getPanelState(FEATURE_OPTIONS_PANEL, true); 88000d183885b54de433e43118d3032340f40cac8c0Chris Banes 8819b1b5bfac6abfda6c7543fc1b57050649b04f41bChris Banes // If we don't have a menu or we're waiting for a full content refresh, 8829b1b5bfac6abfda6c7543fc1b57050649b04f41bChris Banes // forget it. This is a lingering event that no longer matters. 8839b1b5bfac6abfda6c7543fc1b57050649b04f41bChris Banes if (st.menu != null && !st.refreshMenuContent && 8849b1b5bfac6abfda6c7543fc1b57050649b04f41bChris Banes cb.onPreparePanel(FEATURE_OPTIONS_PANEL, null, st.menu)) { 8859b1b5bfac6abfda6c7543fc1b57050649b04f41bChris Banes cb.onMenuOpened(FEATURE_ACTION_BAR, st.menu); 8869b1b5bfac6abfda6c7543fc1b57050649b04f41bChris Banes mDecorContentParent.showOverflowMenu(); 8879b1b5bfac6abfda6c7543fc1b57050649b04f41bChris Banes } 88800d183885b54de433e43118d3032340f40cac8c0Chris Banes } 88900d183885b54de433e43118d3032340f40cac8c0Chris Banes } else { 89000d183885b54de433e43118d3032340f40cac8c0Chris Banes mDecorContentParent.hideOverflowMenu(); 8919b1b5bfac6abfda6c7543fc1b57050649b04f41bChris Banes if (!isDestroyed()) { 8929b1b5bfac6abfda6c7543fc1b57050649b04f41bChris Banes final PanelFeatureState st = getPanelState(FEATURE_OPTIONS_PANEL, true); 8939b1b5bfac6abfda6c7543fc1b57050649b04f41bChris Banes mActivity.onPanelClosed(FEATURE_ACTION_BAR, st.menu); 8949b1b5bfac6abfda6c7543fc1b57050649b04f41bChris Banes } 89500d183885b54de433e43118d3032340f40cac8c0Chris Banes } 89600d183885b54de433e43118d3032340f40cac8c0Chris Banes return; 89700d183885b54de433e43118d3032340f40cac8c0Chris Banes } 89800d183885b54de433e43118d3032340f40cac8c0Chris Banes 89900d183885b54de433e43118d3032340f40cac8c0Chris Banes PanelFeatureState st = getPanelState(FEATURE_OPTIONS_PANEL, true); 90000d183885b54de433e43118d3032340f40cac8c0Chris Banes 90100d183885b54de433e43118d3032340f40cac8c0Chris Banes st.refreshDecorView = true; 90200d183885b54de433e43118d3032340f40cac8c0Chris Banes closePanel(st, false); 90300d183885b54de433e43118d3032340f40cac8c0Chris Banes 90400d183885b54de433e43118d3032340f40cac8c0Chris Banes openPanel(st, null); 90500d183885b54de433e43118d3032340f40cac8c0Chris Banes } 90600d183885b54de433e43118d3032340f40cac8c0Chris Banes 90700d183885b54de433e43118d3032340f40cac8c0Chris Banes private boolean initializePanelMenu(final PanelFeatureState st) { 90861c0bbe56a13fe55ce91a5b1d64e751164ecb894Chris Banes Context context = mActivity; 90961c0bbe56a13fe55ce91a5b1d64e751164ecb894Chris Banes 91000d183885b54de433e43118d3032340f40cac8c0Chris Banes // If we have an action bar, initialize the menu with the right theme. 91100d183885b54de433e43118d3032340f40cac8c0Chris Banes if ((st.featureId == FEATURE_OPTIONS_PANEL || st.featureId == FEATURE_ACTION_BAR) && 91200d183885b54de433e43118d3032340f40cac8c0Chris Banes mDecorContentParent != null) { 91361c0bbe56a13fe55ce91a5b1d64e751164ecb894Chris Banes final TypedValue outValue = new TypedValue(); 91461c0bbe56a13fe55ce91a5b1d64e751164ecb894Chris Banes final Resources.Theme baseTheme = context.getTheme(); 91561c0bbe56a13fe55ce91a5b1d64e751164ecb894Chris Banes baseTheme.resolveAttribute(R.attr.actionBarTheme, outValue, true); 91661c0bbe56a13fe55ce91a5b1d64e751164ecb894Chris Banes 91761c0bbe56a13fe55ce91a5b1d64e751164ecb894Chris Banes Resources.Theme widgetTheme = null; 91861c0bbe56a13fe55ce91a5b1d64e751164ecb894Chris Banes if (outValue.resourceId != 0) { 91961c0bbe56a13fe55ce91a5b1d64e751164ecb894Chris Banes widgetTheme = context.getResources().newTheme(); 92061c0bbe56a13fe55ce91a5b1d64e751164ecb894Chris Banes widgetTheme.setTo(baseTheme); 92161c0bbe56a13fe55ce91a5b1d64e751164ecb894Chris Banes widgetTheme.applyStyle(outValue.resourceId, true); 92261c0bbe56a13fe55ce91a5b1d64e751164ecb894Chris Banes widgetTheme.resolveAttribute( 92361c0bbe56a13fe55ce91a5b1d64e751164ecb894Chris Banes R.attr.actionBarWidgetTheme, outValue, true); 92461c0bbe56a13fe55ce91a5b1d64e751164ecb894Chris Banes } else { 92561c0bbe56a13fe55ce91a5b1d64e751164ecb894Chris Banes baseTheme.resolveAttribute( 92661c0bbe56a13fe55ce91a5b1d64e751164ecb894Chris Banes R.attr.actionBarWidgetTheme, outValue, true); 92761c0bbe56a13fe55ce91a5b1d64e751164ecb894Chris Banes } 92861c0bbe56a13fe55ce91a5b1d64e751164ecb894Chris Banes 92961c0bbe56a13fe55ce91a5b1d64e751164ecb894Chris Banes if (outValue.resourceId != 0) { 93061c0bbe56a13fe55ce91a5b1d64e751164ecb894Chris Banes if (widgetTheme == null) { 93161c0bbe56a13fe55ce91a5b1d64e751164ecb894Chris Banes widgetTheme = context.getResources().newTheme(); 93261c0bbe56a13fe55ce91a5b1d64e751164ecb894Chris Banes widgetTheme.setTo(baseTheme); 93361c0bbe56a13fe55ce91a5b1d64e751164ecb894Chris Banes } 93461c0bbe56a13fe55ce91a5b1d64e751164ecb894Chris Banes widgetTheme.applyStyle(outValue.resourceId, true); 93561c0bbe56a13fe55ce91a5b1d64e751164ecb894Chris Banes } 93661c0bbe56a13fe55ce91a5b1d64e751164ecb894Chris Banes 93761c0bbe56a13fe55ce91a5b1d64e751164ecb894Chris Banes if (widgetTheme != null) { 93861c0bbe56a13fe55ce91a5b1d64e751164ecb894Chris Banes context = new ContextThemeWrapper(context, 0); 93961c0bbe56a13fe55ce91a5b1d64e751164ecb894Chris Banes context.getTheme().setTo(widgetTheme); 94061c0bbe56a13fe55ce91a5b1d64e751164ecb894Chris Banes } 94161c0bbe56a13fe55ce91a5b1d64e751164ecb894Chris Banes } 94261c0bbe56a13fe55ce91a5b1d64e751164ecb894Chris Banes 94300d183885b54de433e43118d3032340f40cac8c0Chris Banes final MenuBuilder menu = new MenuBuilder(context); 94400d183885b54de433e43118d3032340f40cac8c0Chris Banes menu.setCallback(this); 94500d183885b54de433e43118d3032340f40cac8c0Chris Banes st.setMenu(menu); 94661c0bbe56a13fe55ce91a5b1d64e751164ecb894Chris Banes 9478902df1bf0006a156503d40b1fc8a01f95d5b806Chris Banes return true; 9488902df1bf0006a156503d40b1fc8a01f95d5b806Chris Banes } 9498902df1bf0006a156503d40b1fc8a01f95d5b806Chris Banes 95000d183885b54de433e43118d3032340f40cac8c0Chris Banes private boolean initializePanelContent(PanelFeatureState st) { 95100d183885b54de433e43118d3032340f40cac8c0Chris Banes if (st.menu == null) { 95200d183885b54de433e43118d3032340f40cac8c0Chris Banes return false; 95300d183885b54de433e43118d3032340f40cac8c0Chris Banes } 95400d183885b54de433e43118d3032340f40cac8c0Chris Banes 95500d183885b54de433e43118d3032340f40cac8c0Chris Banes if (mPanelMenuPresenterCallback == null) { 95600d183885b54de433e43118d3032340f40cac8c0Chris Banes mPanelMenuPresenterCallback = new PanelMenuPresenterCallback(); 95700d183885b54de433e43118d3032340f40cac8c0Chris Banes } 95800d183885b54de433e43118d3032340f40cac8c0Chris Banes 95957c6de90985a63358129b99b9f0cd4d6afe887d6Chris Banes MenuView menuView = st.getListMenuView(mPanelMenuPresenterCallback); 96000d183885b54de433e43118d3032340f40cac8c0Chris Banes 96100d183885b54de433e43118d3032340f40cac8c0Chris Banes st.shownPanelView = (View) menuView; 96200d183885b54de433e43118d3032340f40cac8c0Chris Banes 96300d183885b54de433e43118d3032340f40cac8c0Chris Banes return st.shownPanelView != null; 96400d183885b54de433e43118d3032340f40cac8c0Chris Banes } 96500d183885b54de433e43118d3032340f40cac8c0Chris Banes 96600d183885b54de433e43118d3032340f40cac8c0Chris Banes private boolean preparePanel(PanelFeatureState st, KeyEvent event) { 9679b1b5bfac6abfda6c7543fc1b57050649b04f41bChris Banes if (isDestroyed()) { 9689b1b5bfac6abfda6c7543fc1b57050649b04f41bChris Banes return false; 9699b1b5bfac6abfda6c7543fc1b57050649b04f41bChris Banes } 9709b1b5bfac6abfda6c7543fc1b57050649b04f41bChris Banes 9718902df1bf0006a156503d40b1fc8a01f95d5b806Chris Banes // Already prepared (isPrepared will be reset to false later) 97200d183885b54de433e43118d3032340f40cac8c0Chris Banes if (st.isPrepared) { 9738902df1bf0006a156503d40b1fc8a01f95d5b806Chris Banes return true; 9748902df1bf0006a156503d40b1fc8a01f95d5b806Chris Banes } 9758902df1bf0006a156503d40b1fc8a01f95d5b806Chris Banes 97600d183885b54de433e43118d3032340f40cac8c0Chris Banes if ((mPreparedPanel != null) && (mPreparedPanel != st)) { 97700d183885b54de433e43118d3032340f40cac8c0Chris Banes // Another Panel is prepared and possibly open, so close it 97800d183885b54de433e43118d3032340f40cac8c0Chris Banes closePanel(mPreparedPanel, false); 97900d183885b54de433e43118d3032340f40cac8c0Chris Banes } 98000d183885b54de433e43118d3032340f40cac8c0Chris Banes 98100d183885b54de433e43118d3032340f40cac8c0Chris Banes final boolean isActionBarMenu = 98200d183885b54de433e43118d3032340f40cac8c0Chris Banes (st.featureId == FEATURE_OPTIONS_PANEL || st.featureId == FEATURE_ACTION_BAR); 98300d183885b54de433e43118d3032340f40cac8c0Chris Banes 98400d183885b54de433e43118d3032340f40cac8c0Chris Banes if (isActionBarMenu && mDecorContentParent != null) { 9858088261dec5dd277ccace13fe00f280ffa80098cChris Banes // Enforce ordering guarantees around events so that the action bar never 9868088261dec5dd277ccace13fe00f280ffa80098cChris Banes // dispatches menu-related events before the panel is prepared. 9878088261dec5dd277ccace13fe00f280ffa80098cChris Banes mDecorContentParent.setMenuPrepared(); 9888088261dec5dd277ccace13fe00f280ffa80098cChris Banes } 9898088261dec5dd277ccace13fe00f280ffa80098cChris Banes 9908902df1bf0006a156503d40b1fc8a01f95d5b806Chris Banes // Init the panel state's menu--return false if init failed 99100d183885b54de433e43118d3032340f40cac8c0Chris Banes if (st.menu == null || st.refreshMenuContent) { 99200d183885b54de433e43118d3032340f40cac8c0Chris Banes if (st.menu == null) { 99300d183885b54de433e43118d3032340f40cac8c0Chris Banes if (!initializePanelMenu(st) || (st.menu == null)) { 9948902df1bf0006a156503d40b1fc8a01f95d5b806Chris Banes return false; 9958902df1bf0006a156503d40b1fc8a01f95d5b806Chris Banes } 9968902df1bf0006a156503d40b1fc8a01f95d5b806Chris Banes } 9978902df1bf0006a156503d40b1fc8a01f95d5b806Chris Banes 99800d183885b54de433e43118d3032340f40cac8c0Chris Banes if (isActionBarMenu && mDecorContentParent != null) { 99903fc11b659da1645507062bddda450136e13af35Chris Banes if (mActionMenuPresenterCallback == null) { 100003fc11b659da1645507062bddda450136e13af35Chris Banes mActionMenuPresenterCallback = new ActionMenuPresenterCallback(); 100103fc11b659da1645507062bddda450136e13af35Chris Banes } 100200d183885b54de433e43118d3032340f40cac8c0Chris Banes mDecorContentParent.setMenu(st.menu, mActionMenuPresenterCallback); 10038902df1bf0006a156503d40b1fc8a01f95d5b806Chris Banes } 10048902df1bf0006a156503d40b1fc8a01f95d5b806Chris Banes 10058902df1bf0006a156503d40b1fc8a01f95d5b806Chris Banes // Creating the panel menu will involve a lot of manipulation; 10068902df1bf0006a156503d40b1fc8a01f95d5b806Chris Banes // don't dispatch change events to presenters until we're done. 100700d183885b54de433e43118d3032340f40cac8c0Chris Banes st.menu.stopDispatchingItemsChanged(); 100800d183885b54de433e43118d3032340f40cac8c0Chris Banes if (!getWindowCallback().onCreatePanelMenu(st.featureId, st.menu)) { 10098902df1bf0006a156503d40b1fc8a01f95d5b806Chris Banes // Ditch the menu created above 101000d183885b54de433e43118d3032340f40cac8c0Chris Banes st.setMenu(null); 10118902df1bf0006a156503d40b1fc8a01f95d5b806Chris Banes 101200d183885b54de433e43118d3032340f40cac8c0Chris Banes if (isActionBarMenu && mDecorContentParent != null) { 10138902df1bf0006a156503d40b1fc8a01f95d5b806Chris Banes // Don't show it in the action bar either 101403fc11b659da1645507062bddda450136e13af35Chris Banes mDecorContentParent.setMenu(null, mActionMenuPresenterCallback); 10158902df1bf0006a156503d40b1fc8a01f95d5b806Chris Banes } 10168902df1bf0006a156503d40b1fc8a01f95d5b806Chris Banes 10178902df1bf0006a156503d40b1fc8a01f95d5b806Chris Banes return false; 10188902df1bf0006a156503d40b1fc8a01f95d5b806Chris Banes } 10198902df1bf0006a156503d40b1fc8a01f95d5b806Chris Banes 102000d183885b54de433e43118d3032340f40cac8c0Chris Banes st.refreshMenuContent = false; 10218902df1bf0006a156503d40b1fc8a01f95d5b806Chris Banes } 10228902df1bf0006a156503d40b1fc8a01f95d5b806Chris Banes 10238902df1bf0006a156503d40b1fc8a01f95d5b806Chris Banes // Preparing the panel menu can involve a lot of manipulation; 10248902df1bf0006a156503d40b1fc8a01f95d5b806Chris Banes // don't dispatch change events to presenters until we're done. 102500d183885b54de433e43118d3032340f40cac8c0Chris Banes st.menu.stopDispatchingItemsChanged(); 10268902df1bf0006a156503d40b1fc8a01f95d5b806Chris Banes 10278902df1bf0006a156503d40b1fc8a01f95d5b806Chris Banes // Restore action view state before we prepare. This gives apps 10288902df1bf0006a156503d40b1fc8a01f95d5b806Chris Banes // an opportunity to override frozen/restored state in onPrepare. 102900d183885b54de433e43118d3032340f40cac8c0Chris Banes if (st.frozenActionViewState != null) { 103000d183885b54de433e43118d3032340f40cac8c0Chris Banes st.menu.restoreActionViewStates(st.frozenActionViewState); 103100d183885b54de433e43118d3032340f40cac8c0Chris Banes st.frozenActionViewState = null; 10328902df1bf0006a156503d40b1fc8a01f95d5b806Chris Banes } 10338902df1bf0006a156503d40b1fc8a01f95d5b806Chris Banes 10348902df1bf0006a156503d40b1fc8a01f95d5b806Chris Banes // Callback and return if the callback does not want to show the menu 103500d183885b54de433e43118d3032340f40cac8c0Chris Banes if (!getWindowCallback().onPreparePanel(FEATURE_OPTIONS_PANEL, null, st.menu)) { 103600d183885b54de433e43118d3032340f40cac8c0Chris Banes if (isActionBarMenu && mDecorContentParent != null) { 10378902df1bf0006a156503d40b1fc8a01f95d5b806Chris Banes // The app didn't want to show the menu for now but it still exists. 10388902df1bf0006a156503d40b1fc8a01f95d5b806Chris Banes // Clear it out of the action bar. 103903fc11b659da1645507062bddda450136e13af35Chris Banes mDecorContentParent.setMenu(null, mActionMenuPresenterCallback); 10408902df1bf0006a156503d40b1fc8a01f95d5b806Chris Banes } 104100d183885b54de433e43118d3032340f40cac8c0Chris Banes st.menu.startDispatchingItemsChanged(); 10428902df1bf0006a156503d40b1fc8a01f95d5b806Chris Banes return false; 10438902df1bf0006a156503d40b1fc8a01f95d5b806Chris Banes } 10448902df1bf0006a156503d40b1fc8a01f95d5b806Chris Banes 104500d183885b54de433e43118d3032340f40cac8c0Chris Banes // Set the proper keymap 104600d183885b54de433e43118d3032340f40cac8c0Chris Banes KeyCharacterMap kmap = KeyCharacterMap.load( 104700d183885b54de433e43118d3032340f40cac8c0Chris Banes event != null ? event.getDeviceId() : KeyCharacterMap.VIRTUAL_KEYBOARD); 104800d183885b54de433e43118d3032340f40cac8c0Chris Banes st.qwertyMode = kmap.getKeyboardType() != KeyCharacterMap.NUMERIC; 104900d183885b54de433e43118d3032340f40cac8c0Chris Banes st.menu.setQwertyMode(st.qwertyMode); 105000d183885b54de433e43118d3032340f40cac8c0Chris Banes st.menu.startDispatchingItemsChanged(); 10518902df1bf0006a156503d40b1fc8a01f95d5b806Chris Banes 10528902df1bf0006a156503d40b1fc8a01f95d5b806Chris Banes // Set other state 105300d183885b54de433e43118d3032340f40cac8c0Chris Banes st.isPrepared = true; 105400d183885b54de433e43118d3032340f40cac8c0Chris Banes st.isHandled = false; 105500d183885b54de433e43118d3032340f40cac8c0Chris Banes mPreparedPanel = st; 10568902df1bf0006a156503d40b1fc8a01f95d5b806Chris Banes 10578902df1bf0006a156503d40b1fc8a01f95d5b806Chris Banes return true; 10588902df1bf0006a156503d40b1fc8a01f95d5b806Chris Banes } 10598902df1bf0006a156503d40b1fc8a01f95d5b806Chris Banes 106000d183885b54de433e43118d3032340f40cac8c0Chris Banes private void checkCloseActionMenu(MenuBuilder menu) { 106103fc11b659da1645507062bddda450136e13af35Chris Banes if (mClosingActionMenu) { 106203fc11b659da1645507062bddda450136e13af35Chris Banes return; 106303fc11b659da1645507062bddda450136e13af35Chris Banes } 106403fc11b659da1645507062bddda450136e13af35Chris Banes 106503fc11b659da1645507062bddda450136e13af35Chris Banes mClosingActionMenu = true; 106603fc11b659da1645507062bddda450136e13af35Chris Banes mDecorContentParent.dismissPopups(); 106700d183885b54de433e43118d3032340f40cac8c0Chris Banes WindowCallback cb = getWindowCallback(); 10689b1b5bfac6abfda6c7543fc1b57050649b04f41bChris Banes if (cb != null && !isDestroyed()) { 106900d183885b54de433e43118d3032340f40cac8c0Chris Banes cb.onPanelClosed(FEATURE_ACTION_BAR, menu); 107000d183885b54de433e43118d3032340f40cac8c0Chris Banes } 107103fc11b659da1645507062bddda450136e13af35Chris Banes mClosingActionMenu = false; 107203fc11b659da1645507062bddda450136e13af35Chris Banes } 107303fc11b659da1645507062bddda450136e13af35Chris Banes 107400d183885b54de433e43118d3032340f40cac8c0Chris Banes private void closePanel(PanelFeatureState st, boolean doCallback) { 107500d183885b54de433e43118d3032340f40cac8c0Chris Banes if (doCallback && st.featureId == FEATURE_OPTIONS_PANEL && 107600d183885b54de433e43118d3032340f40cac8c0Chris Banes mDecorContentParent != null && mDecorContentParent.isOverflowMenuShowing()) { 107700d183885b54de433e43118d3032340f40cac8c0Chris Banes checkCloseActionMenu(st.menu); 107800d183885b54de433e43118d3032340f40cac8c0Chris Banes return; 107900d183885b54de433e43118d3032340f40cac8c0Chris Banes } 108000d183885b54de433e43118d3032340f40cac8c0Chris Banes 108100d183885b54de433e43118d3032340f40cac8c0Chris Banes if (st.isOpen) { 108200d183885b54de433e43118d3032340f40cac8c0Chris Banes if (doCallback) { 108300d183885b54de433e43118d3032340f40cac8c0Chris Banes callOnPanelClosed(st.featureId, st, null); 108400d183885b54de433e43118d3032340f40cac8c0Chris Banes } 108500d183885b54de433e43118d3032340f40cac8c0Chris Banes } 108600d183885b54de433e43118d3032340f40cac8c0Chris Banes 108700d183885b54de433e43118d3032340f40cac8c0Chris Banes st.isPrepared = false; 108800d183885b54de433e43118d3032340f40cac8c0Chris Banes st.isHandled = false; 108900d183885b54de433e43118d3032340f40cac8c0Chris Banes st.isOpen = false; 109000d183885b54de433e43118d3032340f40cac8c0Chris Banes 109100d183885b54de433e43118d3032340f40cac8c0Chris Banes // This view is no longer shown, so null it out 109200d183885b54de433e43118d3032340f40cac8c0Chris Banes st.shownPanelView = null; 109300d183885b54de433e43118d3032340f40cac8c0Chris Banes 109400d183885b54de433e43118d3032340f40cac8c0Chris Banes // Next time the menu opens, it should not be in expanded mode, so 109500d183885b54de433e43118d3032340f40cac8c0Chris Banes // force a refresh of the decor 109600d183885b54de433e43118d3032340f40cac8c0Chris Banes st.refreshDecorView = true; 109700d183885b54de433e43118d3032340f40cac8c0Chris Banes 109800d183885b54de433e43118d3032340f40cac8c0Chris Banes if (mPreparedPanel == st) { 109900d183885b54de433e43118d3032340f40cac8c0Chris Banes mPreparedPanel = null; 110003fc11b659da1645507062bddda450136e13af35Chris Banes } 110103fc11b659da1645507062bddda450136e13af35Chris Banes } 110203fc11b659da1645507062bddda450136e13af35Chris Banes 110300d183885b54de433e43118d3032340f40cac8c0Chris Banes private void callOnPanelClosed(int featureId, PanelFeatureState panel, Menu menu) { 110400d183885b54de433e43118d3032340f40cac8c0Chris Banes // Try to get a menu 110500d183885b54de433e43118d3032340f40cac8c0Chris Banes if (menu == null) { 110600d183885b54de433e43118d3032340f40cac8c0Chris Banes // Need a panel to grab the menu, so try to get that 110700d183885b54de433e43118d3032340f40cac8c0Chris Banes if (panel == null) { 110800d183885b54de433e43118d3032340f40cac8c0Chris Banes if ((featureId >= 0) && (featureId < mPanels.length)) { 110900d183885b54de433e43118d3032340f40cac8c0Chris Banes panel = mPanels[featureId]; 111000d183885b54de433e43118d3032340f40cac8c0Chris Banes } 111100d183885b54de433e43118d3032340f40cac8c0Chris Banes } 111200d183885b54de433e43118d3032340f40cac8c0Chris Banes 111300d183885b54de433e43118d3032340f40cac8c0Chris Banes if (panel != null) { 111400d183885b54de433e43118d3032340f40cac8c0Chris Banes // menu still may be null, which is okay--we tried our best 111500d183885b54de433e43118d3032340f40cac8c0Chris Banes menu = panel.menu; 111600d183885b54de433e43118d3032340f40cac8c0Chris Banes } 111700d183885b54de433e43118d3032340f40cac8c0Chris Banes } 111800d183885b54de433e43118d3032340f40cac8c0Chris Banes 111900d183885b54de433e43118d3032340f40cac8c0Chris Banes // If the panel is not open, do not callback 112000d183885b54de433e43118d3032340f40cac8c0Chris Banes if ((panel != null) && (!panel.isOpen)) 112100d183885b54de433e43118d3032340f40cac8c0Chris Banes return; 112200d183885b54de433e43118d3032340f40cac8c0Chris Banes 112300d183885b54de433e43118d3032340f40cac8c0Chris Banes getWindowCallback().onPanelClosed(featureId, menu); 112400d183885b54de433e43118d3032340f40cac8c0Chris Banes } 112500d183885b54de433e43118d3032340f40cac8c0Chris Banes 112600d183885b54de433e43118d3032340f40cac8c0Chris Banes private PanelFeatureState findMenuPanel(Menu menu) { 112700d183885b54de433e43118d3032340f40cac8c0Chris Banes final PanelFeatureState[] panels = mPanels; 112800d183885b54de433e43118d3032340f40cac8c0Chris Banes final int N = panels != null ? panels.length : 0; 112900d183885b54de433e43118d3032340f40cac8c0Chris Banes for (int i = 0; i < N; i++) { 113000d183885b54de433e43118d3032340f40cac8c0Chris Banes final PanelFeatureState panel = panels[i]; 113100d183885b54de433e43118d3032340f40cac8c0Chris Banes if (panel != null && panel.menu == menu) { 113200d183885b54de433e43118d3032340f40cac8c0Chris Banes return panel; 113300d183885b54de433e43118d3032340f40cac8c0Chris Banes } 113400d183885b54de433e43118d3032340f40cac8c0Chris Banes } 113500d183885b54de433e43118d3032340f40cac8c0Chris Banes return null; 113600d183885b54de433e43118d3032340f40cac8c0Chris Banes } 113700d183885b54de433e43118d3032340f40cac8c0Chris Banes 113800d183885b54de433e43118d3032340f40cac8c0Chris Banes private PanelFeatureState getPanelState(int featureId, boolean required) { 113900d183885b54de433e43118d3032340f40cac8c0Chris Banes PanelFeatureState[] ar; 114000d183885b54de433e43118d3032340f40cac8c0Chris Banes if ((ar = mPanels) == null || ar.length <= featureId) { 114100d183885b54de433e43118d3032340f40cac8c0Chris Banes PanelFeatureState[] nar = new PanelFeatureState[featureId + 1]; 114200d183885b54de433e43118d3032340f40cac8c0Chris Banes if (ar != null) { 114300d183885b54de433e43118d3032340f40cac8c0Chris Banes System.arraycopy(ar, 0, nar, 0, ar.length); 114400d183885b54de433e43118d3032340f40cac8c0Chris Banes } 114500d183885b54de433e43118d3032340f40cac8c0Chris Banes mPanels = ar = nar; 114603fc11b659da1645507062bddda450136e13af35Chris Banes } 114700d183885b54de433e43118d3032340f40cac8c0Chris Banes 114800d183885b54de433e43118d3032340f40cac8c0Chris Banes PanelFeatureState st = ar[featureId]; 114900d183885b54de433e43118d3032340f40cac8c0Chris Banes if (st == null) { 115000d183885b54de433e43118d3032340f40cac8c0Chris Banes ar[featureId] = st = new PanelFeatureState(featureId); 115100d183885b54de433e43118d3032340f40cac8c0Chris Banes } 115200d183885b54de433e43118d3032340f40cac8c0Chris Banes return st; 115303fc11b659da1645507062bddda450136e13af35Chris Banes } 115403fc11b659da1645507062bddda450136e13af35Chris Banes 115500d183885b54de433e43118d3032340f40cac8c0Chris Banes final boolean performPanelShortcut(PanelFeatureState st, int keyCode, KeyEvent event, 115600d183885b54de433e43118d3032340f40cac8c0Chris Banes int flags) { 1157dea1122145ed85590d298a3a9d88ba9f9e2f5f46Chris Banes if (event.isSystem()) { 1158dea1122145ed85590d298a3a9d88ba9f9e2f5f46Chris Banes return false; 1159dea1122145ed85590d298a3a9d88ba9f9e2f5f46Chris Banes } 1160dea1122145ed85590d298a3a9d88ba9f9e2f5f46Chris Banes 1161dea1122145ed85590d298a3a9d88ba9f9e2f5f46Chris Banes boolean handled = false; 1162dea1122145ed85590d298a3a9d88ba9f9e2f5f46Chris Banes 1163dea1122145ed85590d298a3a9d88ba9f9e2f5f46Chris Banes // Only try to perform menu shortcuts if preparePanel returned true (possible false 1164dea1122145ed85590d298a3a9d88ba9f9e2f5f46Chris Banes // return value from application not wanting to show the menu). 116500d183885b54de433e43118d3032340f40cac8c0Chris Banes if ((st.isPrepared || preparePanel(st, event)) && st.menu != null) { 1166dea1122145ed85590d298a3a9d88ba9f9e2f5f46Chris Banes // The menu is prepared now, perform the shortcut on it 116700d183885b54de433e43118d3032340f40cac8c0Chris Banes handled = st.menu.performShortcut(keyCode, event, flags); 1168dea1122145ed85590d298a3a9d88ba9f9e2f5f46Chris Banes } 1169dea1122145ed85590d298a3a9d88ba9f9e2f5f46Chris Banes 1170dea1122145ed85590d298a3a9d88ba9f9e2f5f46Chris Banes if (handled) { 1171dea1122145ed85590d298a3a9d88ba9f9e2f5f46Chris Banes // Only close down the menu if we don't have an action bar keeping it open. 1172dea1122145ed85590d298a3a9d88ba9f9e2f5f46Chris Banes if ((flags & Menu.FLAG_PERFORM_NO_CLOSE) == 0 && mDecorContentParent == null) { 117300d183885b54de433e43118d3032340f40cac8c0Chris Banes closePanel(st, true); 1174dea1122145ed85590d298a3a9d88ba9f9e2f5f46Chris Banes } 1175dea1122145ed85590d298a3a9d88ba9f9e2f5f46Chris Banes } 1176dea1122145ed85590d298a3a9d88ba9f9e2f5f46Chris Banes 1177dea1122145ed85590d298a3a9d88ba9f9e2f5f46Chris Banes return handled; 1178dea1122145ed85590d298a3a9d88ba9f9e2f5f46Chris Banes } 1179dea1122145ed85590d298a3a9d88ba9f9e2f5f46Chris Banes 118000d183885b54de433e43118d3032340f40cac8c0Chris Banes private void invalidatePanelMenu(int featureId) { 118100d183885b54de433e43118d3032340f40cac8c0Chris Banes mInvalidatePanelMenuFeatures |= 1 << featureId; 118200d183885b54de433e43118d3032340f40cac8c0Chris Banes 118300d183885b54de433e43118d3032340f40cac8c0Chris Banes if (!mInvalidatePanelMenuPosted && mWindowDecor != null) { 118400d183885b54de433e43118d3032340f40cac8c0Chris Banes ViewCompat.postOnAnimation(mWindowDecor, mInvalidatePanelMenuRunnable); 118500d183885b54de433e43118d3032340f40cac8c0Chris Banes mInvalidatePanelMenuPosted = true; 118600d183885b54de433e43118d3032340f40cac8c0Chris Banes } 118700d183885b54de433e43118d3032340f40cac8c0Chris Banes } 118800d183885b54de433e43118d3032340f40cac8c0Chris Banes 118900d183885b54de433e43118d3032340f40cac8c0Chris Banes private void doInvalidatePanelMenu(int featureId) { 119000d183885b54de433e43118d3032340f40cac8c0Chris Banes PanelFeatureState st = getPanelState(featureId, true); 119100d183885b54de433e43118d3032340f40cac8c0Chris Banes Bundle savedActionViewStates = null; 119200d183885b54de433e43118d3032340f40cac8c0Chris Banes if (st.menu != null) { 119300d183885b54de433e43118d3032340f40cac8c0Chris Banes savedActionViewStates = new Bundle(); 119400d183885b54de433e43118d3032340f40cac8c0Chris Banes st.menu.saveActionViewStates(savedActionViewStates); 119500d183885b54de433e43118d3032340f40cac8c0Chris Banes if (savedActionViewStates.size() > 0) { 119600d183885b54de433e43118d3032340f40cac8c0Chris Banes st.frozenActionViewState = savedActionViewStates; 119700d183885b54de433e43118d3032340f40cac8c0Chris Banes } 119800d183885b54de433e43118d3032340f40cac8c0Chris Banes // This will be started again when the panel is prepared. 119900d183885b54de433e43118d3032340f40cac8c0Chris Banes st.menu.stopDispatchingItemsChanged(); 120000d183885b54de433e43118d3032340f40cac8c0Chris Banes st.menu.clear(); 120100d183885b54de433e43118d3032340f40cac8c0Chris Banes } 120200d183885b54de433e43118d3032340f40cac8c0Chris Banes st.refreshMenuContent = true; 120300d183885b54de433e43118d3032340f40cac8c0Chris Banes st.refreshDecorView = true; 120400d183885b54de433e43118d3032340f40cac8c0Chris Banes 120500d183885b54de433e43118d3032340f40cac8c0Chris Banes // Prepare the options panel if we have an action bar 120600d183885b54de433e43118d3032340f40cac8c0Chris Banes if ((featureId == FEATURE_ACTION_BAR || featureId == FEATURE_OPTIONS_PANEL) 120700d183885b54de433e43118d3032340f40cac8c0Chris Banes && mDecorContentParent != null) { 120800d183885b54de433e43118d3032340f40cac8c0Chris Banes st = getPanelState(Window.FEATURE_OPTIONS_PANEL, false); 120900d183885b54de433e43118d3032340f40cac8c0Chris Banes if (st != null) { 121000d183885b54de433e43118d3032340f40cac8c0Chris Banes st.isPrepared = false; 121100d183885b54de433e43118d3032340f40cac8c0Chris Banes preparePanel(st, null); 121200d183885b54de433e43118d3032340f40cac8c0Chris Banes } 121300d183885b54de433e43118d3032340f40cac8c0Chris Banes } 121400d183885b54de433e43118d3032340f40cac8c0Chris Banes } 121500d183885b54de433e43118d3032340f40cac8c0Chris Banes 1216ea4f700ac38424954c56df5138ff794def50b019Chris Banes /** 1217ea4f700ac38424954c56df5138ff794def50b019Chris Banes * Updates the status bar guard 1218ea4f700ac38424954c56df5138ff794def50b019Chris Banes * 1219ea4f700ac38424954c56df5138ff794def50b019Chris Banes * @param insetTop the current top system window inset 1220ea4f700ac38424954c56df5138ff794def50b019Chris Banes * @return the new top system window inset 1221ea4f700ac38424954c56df5138ff794def50b019Chris Banes */ 1222ea4f700ac38424954c56df5138ff794def50b019Chris Banes private int updateStatusGuard(int insetTop) { 1223ec3f49d21a507835c1f50ce5600000b587a2af08Chris Banes boolean showStatusGuard = false; 1224ec3f49d21a507835c1f50ce5600000b587a2af08Chris Banes // Show the status guard when the non-overlay contextual action bar is showing 1225ec3f49d21a507835c1f50ce5600000b587a2af08Chris Banes if (mActionModeView != null) { 1226ec3f49d21a507835c1f50ce5600000b587a2af08Chris Banes if (mActionModeView.getLayoutParams() instanceof ViewGroup.MarginLayoutParams) { 1227ec3f49d21a507835c1f50ce5600000b587a2af08Chris Banes ViewGroup.MarginLayoutParams mlp = (ViewGroup.MarginLayoutParams) 1228ec3f49d21a507835c1f50ce5600000b587a2af08Chris Banes mActionModeView.getLayoutParams(); 1229ec3f49d21a507835c1f50ce5600000b587a2af08Chris Banes boolean mlpChanged = false; 1230ec3f49d21a507835c1f50ce5600000b587a2af08Chris Banes 1231ec3f49d21a507835c1f50ce5600000b587a2af08Chris Banes if (mActionModeView.isShown()) { 12327efc56b68ff933dfeeac81dd2d8a32096b90f0f4Adam Powell if (mTempRect1 == null) { 12337efc56b68ff933dfeeac81dd2d8a32096b90f0f4Adam Powell mTempRect1 = new Rect(); 12347efc56b68ff933dfeeac81dd2d8a32096b90f0f4Adam Powell mTempRect2 = new Rect(); 12357efc56b68ff933dfeeac81dd2d8a32096b90f0f4Adam Powell } 12367efc56b68ff933dfeeac81dd2d8a32096b90f0f4Adam Powell final Rect insets = mTempRect1; 12377efc56b68ff933dfeeac81dd2d8a32096b90f0f4Adam Powell final Rect localInsets = mTempRect2; 12387efc56b68ff933dfeeac81dd2d8a32096b90f0f4Adam Powell insets.set(0, insetTop, 0, 0); 12397efc56b68ff933dfeeac81dd2d8a32096b90f0f4Adam Powell 12407efc56b68ff933dfeeac81dd2d8a32096b90f0f4Adam Powell ViewUtils.computeFitSystemWindows(mSubDecor, insets, localInsets); 12417efc56b68ff933dfeeac81dd2d8a32096b90f0f4Adam Powell final int newMargin = localInsets.top == 0 ? insetTop : 0; 12427efc56b68ff933dfeeac81dd2d8a32096b90f0f4Adam Powell if (mlp.topMargin != newMargin) { 12437efc56b68ff933dfeeac81dd2d8a32096b90f0f4Adam Powell mlpChanged = true; 12447efc56b68ff933dfeeac81dd2d8a32096b90f0f4Adam Powell mlp.topMargin = insetTop; 12457efc56b68ff933dfeeac81dd2d8a32096b90f0f4Adam Powell 1246ec3f49d21a507835c1f50ce5600000b587a2af08Chris Banes if (mStatusGuard == null) { 1247ec3f49d21a507835c1f50ce5600000b587a2af08Chris Banes mStatusGuard = new View(mActivity); 1248ec3f49d21a507835c1f50ce5600000b587a2af08Chris Banes mStatusGuard.setBackgroundColor(mActivity.getResources() 1249ec3f49d21a507835c1f50ce5600000b587a2af08Chris Banes .getColor(R.color.abc_input_method_navigation_guard)); 12507efc56b68ff933dfeeac81dd2d8a32096b90f0f4Adam Powell mSubDecor.addView(mStatusGuard, -1, 1251ec3f49d21a507835c1f50ce5600000b587a2af08Chris Banes new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, 1252ec3f49d21a507835c1f50ce5600000b587a2af08Chris Banes insetTop)); 1253ec3f49d21a507835c1f50ce5600000b587a2af08Chris Banes } else { 1254ec3f49d21a507835c1f50ce5600000b587a2af08Chris Banes ViewGroup.LayoutParams lp = mStatusGuard.getLayoutParams(); 1255ec3f49d21a507835c1f50ce5600000b587a2af08Chris Banes if (lp.height != insetTop) { 1256ec3f49d21a507835c1f50ce5600000b587a2af08Chris Banes lp.height = insetTop; 1257ec3f49d21a507835c1f50ce5600000b587a2af08Chris Banes mStatusGuard.setLayoutParams(lp); 1258ec3f49d21a507835c1f50ce5600000b587a2af08Chris Banes } 1259ec3f49d21a507835c1f50ce5600000b587a2af08Chris Banes } 1260ec3f49d21a507835c1f50ce5600000b587a2af08Chris Banes } 1261ec3f49d21a507835c1f50ce5600000b587a2af08Chris Banes 1262bbb50c78cc6ee24677c79bd4548fa38fcdc41d92Adam Powell // The action mode's theme may differ from the app, so 1263bbb50c78cc6ee24677c79bd4548fa38fcdc41d92Adam Powell // always show the status guard above it. 1264bbb50c78cc6ee24677c79bd4548fa38fcdc41d92Adam Powell showStatusGuard = mStatusGuard != null; 1265bbb50c78cc6ee24677c79bd4548fa38fcdc41d92Adam Powell 12667efc56b68ff933dfeeac81dd2d8a32096b90f0f4Adam Powell // We only need to consume the insets if the action 12677efc56b68ff933dfeeac81dd2d8a32096b90f0f4Adam Powell // mode is overlaid on the app content (e.g. it's 12687efc56b68ff933dfeeac81dd2d8a32096b90f0f4Adam Powell // sitting in a FrameLayout, see 12697efc56b68ff933dfeeac81dd2d8a32096b90f0f4Adam Powell // screen_simple_overlay_action_mode.xml). 1270bbb50c78cc6ee24677c79bd4548fa38fcdc41d92Adam Powell if (!mOverlayActionMode && showStatusGuard) { 12717efc56b68ff933dfeeac81dd2d8a32096b90f0f4Adam Powell insetTop = 0; 12727efc56b68ff933dfeeac81dd2d8a32096b90f0f4Adam Powell } 1273ec3f49d21a507835c1f50ce5600000b587a2af08Chris Banes } else { 1274ec3f49d21a507835c1f50ce5600000b587a2af08Chris Banes // reset top margin 1275ec3f49d21a507835c1f50ce5600000b587a2af08Chris Banes if (mlp.topMargin != 0) { 1276ec3f49d21a507835c1f50ce5600000b587a2af08Chris Banes mlpChanged = true; 1277ec3f49d21a507835c1f50ce5600000b587a2af08Chris Banes mlp.topMargin = 0; 1278ec3f49d21a507835c1f50ce5600000b587a2af08Chris Banes } 1279ec3f49d21a507835c1f50ce5600000b587a2af08Chris Banes } 1280ec3f49d21a507835c1f50ce5600000b587a2af08Chris Banes if (mlpChanged) { 1281ec3f49d21a507835c1f50ce5600000b587a2af08Chris Banes mActionModeView.setLayoutParams(mlp); 1282ec3f49d21a507835c1f50ce5600000b587a2af08Chris Banes } 1283ec3f49d21a507835c1f50ce5600000b587a2af08Chris Banes } 1284ec3f49d21a507835c1f50ce5600000b587a2af08Chris Banes } 1285ec3f49d21a507835c1f50ce5600000b587a2af08Chris Banes if (mStatusGuard != null) { 1286ec3f49d21a507835c1f50ce5600000b587a2af08Chris Banes mStatusGuard.setVisibility(showStatusGuard ? View.VISIBLE : View.GONE); 1287ec3f49d21a507835c1f50ce5600000b587a2af08Chris Banes } 1288ea4f700ac38424954c56df5138ff794def50b019Chris Banes 1289ea4f700ac38424954c56df5138ff794def50b019Chris Banes return insetTop; 1290ec3f49d21a507835c1f50ce5600000b587a2af08Chris Banes } 1291ec3f49d21a507835c1f50ce5600000b587a2af08Chris Banes 1292da0b9d63d6f940cbfd5b526c3f81858aeadcb7e8Chris Banes private void ensureToolbarListMenuPresenter() { 1293da0b9d63d6f940cbfd5b526c3f81858aeadcb7e8Chris Banes if (mToolbarListMenuPresenter == null) { 1294da0b9d63d6f940cbfd5b526c3f81858aeadcb7e8Chris Banes // First resolve panelMenuListTheme 1295da0b9d63d6f940cbfd5b526c3f81858aeadcb7e8Chris Banes TypedValue outValue = new TypedValue(); 1296da0b9d63d6f940cbfd5b526c3f81858aeadcb7e8Chris Banes mActivity.getTheme().resolveAttribute(R.attr.panelMenuListTheme, outValue, true); 1297da0b9d63d6f940cbfd5b526c3f81858aeadcb7e8Chris Banes 1298da0b9d63d6f940cbfd5b526c3f81858aeadcb7e8Chris Banes Context context = new ContextThemeWrapper(mActivity, 1299da0b9d63d6f940cbfd5b526c3f81858aeadcb7e8Chris Banes outValue.resourceId != 0 1300da0b9d63d6f940cbfd5b526c3f81858aeadcb7e8Chris Banes ? outValue.resourceId 1301da0b9d63d6f940cbfd5b526c3f81858aeadcb7e8Chris Banes : R.style.Theme_AppCompat_CompactMenu); 1302da0b9d63d6f940cbfd5b526c3f81858aeadcb7e8Chris Banes 1303da0b9d63d6f940cbfd5b526c3f81858aeadcb7e8Chris Banes mToolbarListMenuPresenter = new ListMenuPresenter(context, 1304da0b9d63d6f940cbfd5b526c3f81858aeadcb7e8Chris Banes R.layout.abc_list_menu_item_layout); 1305da0b9d63d6f940cbfd5b526c3f81858aeadcb7e8Chris Banes } 1306da0b9d63d6f940cbfd5b526c3f81858aeadcb7e8Chris Banes } 1307da0b9d63d6f940cbfd5b526c3f81858aeadcb7e8Chris Banes 1308cc7aada3ee922cfb38eeb36ee696cc73dcbae0a4Chris Banes private void throwFeatureRequestIfSubDecorInstalled() { 1309cc7aada3ee922cfb38eeb36ee696cc73dcbae0a4Chris Banes if (mSubDecorInstalled) { 1310cc7aada3ee922cfb38eeb36ee696cc73dcbae0a4Chris Banes throw new AndroidRuntimeException( 1311cc7aada3ee922cfb38eeb36ee696cc73dcbae0a4Chris Banes "supportRequestWindowFeature() must be called before adding content"); 1312cc7aada3ee922cfb38eeb36ee696cc73dcbae0a4Chris Banes } 1313cc7aada3ee922cfb38eeb36ee696cc73dcbae0a4Chris Banes } 1314cc7aada3ee922cfb38eeb36ee696cc73dcbae0a4Chris Banes 1315ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes /** 1316d8222dedaacae30fa03bee346ebf42ee75b39928Chris Banes * Clears out internal reference when the action mode is destroyed. 1317d8222dedaacae30fa03bee346ebf42ee75b39928Chris Banes */ 1318d8222dedaacae30fa03bee346ebf42ee75b39928Chris Banes private class ActionModeCallbackWrapper implements ActionMode.Callback { 1319d8222dedaacae30fa03bee346ebf42ee75b39928Chris Banes private ActionMode.Callback mWrapped; 1320d8222dedaacae30fa03bee346ebf42ee75b39928Chris Banes 1321d8222dedaacae30fa03bee346ebf42ee75b39928Chris Banes public ActionModeCallbackWrapper(ActionMode.Callback wrapped) { 1322d8222dedaacae30fa03bee346ebf42ee75b39928Chris Banes mWrapped = wrapped; 1323d8222dedaacae30fa03bee346ebf42ee75b39928Chris Banes } 1324d8222dedaacae30fa03bee346ebf42ee75b39928Chris Banes 1325d8222dedaacae30fa03bee346ebf42ee75b39928Chris Banes public boolean onCreateActionMode(ActionMode mode, Menu menu) { 1326d8222dedaacae30fa03bee346ebf42ee75b39928Chris Banes return mWrapped.onCreateActionMode(mode, menu); 1327d8222dedaacae30fa03bee346ebf42ee75b39928Chris Banes } 1328d8222dedaacae30fa03bee346ebf42ee75b39928Chris Banes 1329d8222dedaacae30fa03bee346ebf42ee75b39928Chris Banes public boolean onPrepareActionMode(ActionMode mode, Menu menu) { 13309addcff1698f71fb4145f39dacaf33a9c1fef24fChris Banes return mWrapped.onPrepareActionMode(mode, menu); 1331d8222dedaacae30fa03bee346ebf42ee75b39928Chris Banes } 1332d8222dedaacae30fa03bee346ebf42ee75b39928Chris Banes 1333d8222dedaacae30fa03bee346ebf42ee75b39928Chris Banes public boolean onActionItemClicked(ActionMode mode, MenuItem item) { 1334d8222dedaacae30fa03bee346ebf42ee75b39928Chris Banes return mWrapped.onActionItemClicked(mode, item); 1335d8222dedaacae30fa03bee346ebf42ee75b39928Chris Banes } 1336d8222dedaacae30fa03bee346ebf42ee75b39928Chris Banes 1337d8222dedaacae30fa03bee346ebf42ee75b39928Chris Banes public void onDestroyActionMode(ActionMode mode) { 1338d8222dedaacae30fa03bee346ebf42ee75b39928Chris Banes mWrapped.onDestroyActionMode(mode); 13394c2a95906254748cb9a843b061288265d6e185a9Chris Banes if (mActionModePopup != null) { 13404c2a95906254748cb9a843b061288265d6e185a9Chris Banes mActivity.getWindow().getDecorView().removeCallbacks(mShowActionModePopup); 13414c2a95906254748cb9a843b061288265d6e185a9Chris Banes mActionModePopup.dismiss(); 13424c2a95906254748cb9a843b061288265d6e185a9Chris Banes } else if (mActionModeView != null) { 13434c2a95906254748cb9a843b061288265d6e185a9Chris Banes mActionModeView.setVisibility(View.GONE); 1344ec3f49d21a507835c1f50ce5600000b587a2af08Chris Banes if (mActionModeView.getParent() != null) { 1345ec3f49d21a507835c1f50ce5600000b587a2af08Chris Banes ViewCompat.requestApplyInsets((View) mActionModeView.getParent()); 1346ec3f49d21a507835c1f50ce5600000b587a2af08Chris Banes } 13474c2a95906254748cb9a843b061288265d6e185a9Chris Banes } 13484c2a95906254748cb9a843b061288265d6e185a9Chris Banes if (mActionModeView != null) { 13494c2a95906254748cb9a843b061288265d6e185a9Chris Banes mActionModeView.removeAllViews(); 13504c2a95906254748cb9a843b061288265d6e185a9Chris Banes } 13514c2a95906254748cb9a843b061288265d6e185a9Chris Banes if (mActivity != null) { 13524c2a95906254748cb9a843b061288265d6e185a9Chris Banes try { 13534c2a95906254748cb9a843b061288265d6e185a9Chris Banes mActivity.onSupportActionModeFinished(mActionMode); 13544c2a95906254748cb9a843b061288265d6e185a9Chris Banes } catch (AbstractMethodError ame) { 13554c2a95906254748cb9a843b061288265d6e185a9Chris Banes // Older apps might not implement this callback method. 13564c2a95906254748cb9a843b061288265d6e185a9Chris Banes } 13574c2a95906254748cb9a843b061288265d6e185a9Chris Banes } 1358d8222dedaacae30fa03bee346ebf42ee75b39928Chris Banes mActionMode = null; 1359d8222dedaacae30fa03bee346ebf42ee75b39928Chris Banes } 1360d8222dedaacae30fa03bee346ebf42ee75b39928Chris Banes } 1361d8222dedaacae30fa03bee346ebf42ee75b39928Chris Banes 136203fc11b659da1645507062bddda450136e13af35Chris Banes private final class PanelMenuPresenterCallback implements MenuPresenter.Callback { 136303fc11b659da1645507062bddda450136e13af35Chris Banes @Override 136400d183885b54de433e43118d3032340f40cac8c0Chris Banes public void onCloseMenu(MenuBuilder menu, boolean allMenusAreClosing) { 136500d183885b54de433e43118d3032340f40cac8c0Chris Banes final Menu parentMenu = menu.getRootMenu(); 136600d183885b54de433e43118d3032340f40cac8c0Chris Banes final boolean isSubMenu = parentMenu != menu; 136700d183885b54de433e43118d3032340f40cac8c0Chris Banes final PanelFeatureState panel = findMenuPanel(isSubMenu ? parentMenu : menu); 136800d183885b54de433e43118d3032340f40cac8c0Chris Banes if (panel != null) { 136900d183885b54de433e43118d3032340f40cac8c0Chris Banes if (isSubMenu) { 137000d183885b54de433e43118d3032340f40cac8c0Chris Banes callOnPanelClosed(panel.featureId, panel, parentMenu); 137100d183885b54de433e43118d3032340f40cac8c0Chris Banes closePanel(panel, true); 137200d183885b54de433e43118d3032340f40cac8c0Chris Banes } else { 137300d183885b54de433e43118d3032340f40cac8c0Chris Banes // Close the panel and only do the callback if the menu is being 137400d183885b54de433e43118d3032340f40cac8c0Chris Banes // closed completely, not if opening a sub menu 137528cca4bf59e7f3fd35f9da05caa9418251b5227aChris Banes mActivity.closeOptionsMenu(); 137600d183885b54de433e43118d3032340f40cac8c0Chris Banes closePanel(panel, allMenusAreClosing); 137700d183885b54de433e43118d3032340f40cac8c0Chris Banes } 137800d183885b54de433e43118d3032340f40cac8c0Chris Banes } 137903fc11b659da1645507062bddda450136e13af35Chris Banes } 138003fc11b659da1645507062bddda450136e13af35Chris Banes 138103fc11b659da1645507062bddda450136e13af35Chris Banes @Override 138200d183885b54de433e43118d3032340f40cac8c0Chris Banes public boolean onOpenSubMenu(MenuBuilder subMenu) { 138300d183885b54de433e43118d3032340f40cac8c0Chris Banes if (subMenu == null && mHasActionBar) { 138400d183885b54de433e43118d3032340f40cac8c0Chris Banes WindowCallback cb = getWindowCallback(); 13859b1b5bfac6abfda6c7543fc1b57050649b04f41bChris Banes if (cb != null && !isDestroyed()) { 138600d183885b54de433e43118d3032340f40cac8c0Chris Banes cb.onMenuOpened(FEATURE_ACTION_BAR, subMenu); 138700d183885b54de433e43118d3032340f40cac8c0Chris Banes } 138800d183885b54de433e43118d3032340f40cac8c0Chris Banes } 138900d183885b54de433e43118d3032340f40cac8c0Chris Banes return true; 139003fc11b659da1645507062bddda450136e13af35Chris Banes } 139103fc11b659da1645507062bddda450136e13af35Chris Banes } 139203fc11b659da1645507062bddda450136e13af35Chris Banes 139303fc11b659da1645507062bddda450136e13af35Chris Banes private final class ActionMenuPresenterCallback implements MenuPresenter.Callback { 139403fc11b659da1645507062bddda450136e13af35Chris Banes @Override 139503fc11b659da1645507062bddda450136e13af35Chris Banes public boolean onOpenSubMenu(MenuBuilder subMenu) { 139600d183885b54de433e43118d3032340f40cac8c0Chris Banes WindowCallback cb = getWindowCallback(); 139700d183885b54de433e43118d3032340f40cac8c0Chris Banes if (cb != null) { 139800d183885b54de433e43118d3032340f40cac8c0Chris Banes cb.onMenuOpened(FEATURE_ACTION_BAR, subMenu); 139900d183885b54de433e43118d3032340f40cac8c0Chris Banes } 140000d183885b54de433e43118d3032340f40cac8c0Chris Banes return true; 140103fc11b659da1645507062bddda450136e13af35Chris Banes } 140203fc11b659da1645507062bddda450136e13af35Chris Banes 140303fc11b659da1645507062bddda450136e13af35Chris Banes @Override 140403fc11b659da1645507062bddda450136e13af35Chris Banes public void onCloseMenu(MenuBuilder menu, boolean allMenusAreClosing) { 140500d183885b54de433e43118d3032340f40cac8c0Chris Banes checkCloseActionMenu(menu); 140600d183885b54de433e43118d3032340f40cac8c0Chris Banes } 140700d183885b54de433e43118d3032340f40cac8c0Chris Banes } 140800d183885b54de433e43118d3032340f40cac8c0Chris Banes 140900d183885b54de433e43118d3032340f40cac8c0Chris Banes private static final class PanelFeatureState { 14109b1b5bfac6abfda6c7543fc1b57050649b04f41bChris Banes 141100d183885b54de433e43118d3032340f40cac8c0Chris Banes /** Feature ID for this panel. */ 141200d183885b54de433e43118d3032340f40cac8c0Chris Banes int featureId; 141300d183885b54de433e43118d3032340f40cac8c0Chris Banes 141400d183885b54de433e43118d3032340f40cac8c0Chris Banes /** Dynamic state of the panel. */ 141500d183885b54de433e43118d3032340f40cac8c0Chris Banes ViewGroup decorView; 141600d183885b54de433e43118d3032340f40cac8c0Chris Banes 141700d183885b54de433e43118d3032340f40cac8c0Chris Banes /** The panel that we are actually showing. */ 141800d183885b54de433e43118d3032340f40cac8c0Chris Banes View shownPanelView; 141900d183885b54de433e43118d3032340f40cac8c0Chris Banes 142000d183885b54de433e43118d3032340f40cac8c0Chris Banes /** Use {@link #setMenu} to set this. */ 142100d183885b54de433e43118d3032340f40cac8c0Chris Banes MenuBuilder menu; 142200d183885b54de433e43118d3032340f40cac8c0Chris Banes 142300d183885b54de433e43118d3032340f40cac8c0Chris Banes ListMenuPresenter listMenuPresenter; 142400d183885b54de433e43118d3032340f40cac8c0Chris Banes 142557c6de90985a63358129b99b9f0cd4d6afe887d6Chris Banes Context listPresenterContext; 142600d183885b54de433e43118d3032340f40cac8c0Chris Banes 142700d183885b54de433e43118d3032340f40cac8c0Chris Banes /** 142800d183885b54de433e43118d3032340f40cac8c0Chris Banes * Whether the panel has been prepared (see 14299b1b5bfac6abfda6c7543fc1b57050649b04f41bChris Banes * {@link #preparePanel}). 143000d183885b54de433e43118d3032340f40cac8c0Chris Banes */ 143100d183885b54de433e43118d3032340f40cac8c0Chris Banes boolean isPrepared; 143200d183885b54de433e43118d3032340f40cac8c0Chris Banes 143300d183885b54de433e43118d3032340f40cac8c0Chris Banes /** 143400d183885b54de433e43118d3032340f40cac8c0Chris Banes * Whether an item's action has been performed. This happens in obvious 143500d183885b54de433e43118d3032340f40cac8c0Chris Banes * scenarios (user clicks on menu item), but can also happen with 143600d183885b54de433e43118d3032340f40cac8c0Chris Banes * chording menu+(shortcut key). 143700d183885b54de433e43118d3032340f40cac8c0Chris Banes */ 143800d183885b54de433e43118d3032340f40cac8c0Chris Banes boolean isHandled; 143900d183885b54de433e43118d3032340f40cac8c0Chris Banes 144000d183885b54de433e43118d3032340f40cac8c0Chris Banes boolean isOpen; 144100d183885b54de433e43118d3032340f40cac8c0Chris Banes 144200d183885b54de433e43118d3032340f40cac8c0Chris Banes public boolean qwertyMode; 144300d183885b54de433e43118d3032340f40cac8c0Chris Banes 144400d183885b54de433e43118d3032340f40cac8c0Chris Banes boolean refreshDecorView; 144500d183885b54de433e43118d3032340f40cac8c0Chris Banes 144600d183885b54de433e43118d3032340f40cac8c0Chris Banes boolean refreshMenuContent; 144700d183885b54de433e43118d3032340f40cac8c0Chris Banes 144800d183885b54de433e43118d3032340f40cac8c0Chris Banes boolean wasLastOpen; 144900d183885b54de433e43118d3032340f40cac8c0Chris Banes 145000d183885b54de433e43118d3032340f40cac8c0Chris Banes /** 145100d183885b54de433e43118d3032340f40cac8c0Chris Banes * Contains the state of the menu when told to freeze. 145200d183885b54de433e43118d3032340f40cac8c0Chris Banes */ 145300d183885b54de433e43118d3032340f40cac8c0Chris Banes Bundle frozenMenuState; 145400d183885b54de433e43118d3032340f40cac8c0Chris Banes 145500d183885b54de433e43118d3032340f40cac8c0Chris Banes /** 145600d183885b54de433e43118d3032340f40cac8c0Chris Banes * Contains the state of associated action views when told to freeze. 145700d183885b54de433e43118d3032340f40cac8c0Chris Banes * These are saved across invalidations. 145800d183885b54de433e43118d3032340f40cac8c0Chris Banes */ 145900d183885b54de433e43118d3032340f40cac8c0Chris Banes Bundle frozenActionViewState; 146000d183885b54de433e43118d3032340f40cac8c0Chris Banes 146100d183885b54de433e43118d3032340f40cac8c0Chris Banes PanelFeatureState(int featureId) { 146200d183885b54de433e43118d3032340f40cac8c0Chris Banes this.featureId = featureId; 146300d183885b54de433e43118d3032340f40cac8c0Chris Banes 146400d183885b54de433e43118d3032340f40cac8c0Chris Banes refreshDecorView = false; 146500d183885b54de433e43118d3032340f40cac8c0Chris Banes } 146600d183885b54de433e43118d3032340f40cac8c0Chris Banes 146700d183885b54de433e43118d3032340f40cac8c0Chris Banes public boolean hasPanelItems() { 146800d183885b54de433e43118d3032340f40cac8c0Chris Banes if (shownPanelView == null) return false; 146900d183885b54de433e43118d3032340f40cac8c0Chris Banes 147000d183885b54de433e43118d3032340f40cac8c0Chris Banes return listMenuPresenter.getAdapter().getCount() > 0; 147100d183885b54de433e43118d3032340f40cac8c0Chris Banes } 147200d183885b54de433e43118d3032340f40cac8c0Chris Banes 147300d183885b54de433e43118d3032340f40cac8c0Chris Banes /** 147400d183885b54de433e43118d3032340f40cac8c0Chris Banes * Unregister and free attached MenuPresenters. They will be recreated as needed. 147500d183885b54de433e43118d3032340f40cac8c0Chris Banes */ 147600d183885b54de433e43118d3032340f40cac8c0Chris Banes public void clearMenuPresenters() { 147700d183885b54de433e43118d3032340f40cac8c0Chris Banes if (menu != null) { 147800d183885b54de433e43118d3032340f40cac8c0Chris Banes menu.removeMenuPresenter(listMenuPresenter); 147900d183885b54de433e43118d3032340f40cac8c0Chris Banes } 148000d183885b54de433e43118d3032340f40cac8c0Chris Banes listMenuPresenter = null; 148100d183885b54de433e43118d3032340f40cac8c0Chris Banes } 148200d183885b54de433e43118d3032340f40cac8c0Chris Banes 148300d183885b54de433e43118d3032340f40cac8c0Chris Banes void setStyle(Context context) { 148457c6de90985a63358129b99b9f0cd4d6afe887d6Chris Banes final TypedValue outValue = new TypedValue(); 148557c6de90985a63358129b99b9f0cd4d6afe887d6Chris Banes final Resources.Theme widgetTheme = context.getResources().newTheme(); 148657c6de90985a63358129b99b9f0cd4d6afe887d6Chris Banes widgetTheme.setTo(context.getTheme()); 148757c6de90985a63358129b99b9f0cd4d6afe887d6Chris Banes 148857c6de90985a63358129b99b9f0cd4d6afe887d6Chris Banes // First apply the actionBarPopupTheme 148957c6de90985a63358129b99b9f0cd4d6afe887d6Chris Banes widgetTheme.resolveAttribute(R.attr.actionBarPopupTheme, outValue, true); 149057c6de90985a63358129b99b9f0cd4d6afe887d6Chris Banes if (outValue.resourceId != 0) { 149157c6de90985a63358129b99b9f0cd4d6afe887d6Chris Banes widgetTheme.applyStyle(outValue.resourceId, true); 149257c6de90985a63358129b99b9f0cd4d6afe887d6Chris Banes } 149357c6de90985a63358129b99b9f0cd4d6afe887d6Chris Banes 149457c6de90985a63358129b99b9f0cd4d6afe887d6Chris Banes // Now apply the panelMenuListTheme 149557c6de90985a63358129b99b9f0cd4d6afe887d6Chris Banes widgetTheme.resolveAttribute(R.attr.panelMenuListTheme, outValue, true); 149657c6de90985a63358129b99b9f0cd4d6afe887d6Chris Banes if (outValue.resourceId != 0) { 149757c6de90985a63358129b99b9f0cd4d6afe887d6Chris Banes widgetTheme.applyStyle(outValue.resourceId, true); 149857c6de90985a63358129b99b9f0cd4d6afe887d6Chris Banes } else { 149957c6de90985a63358129b99b9f0cd4d6afe887d6Chris Banes widgetTheme.applyStyle(R.style.Theme_AppCompat_CompactMenu, true); 150057c6de90985a63358129b99b9f0cd4d6afe887d6Chris Banes } 150157c6de90985a63358129b99b9f0cd4d6afe887d6Chris Banes 150257c6de90985a63358129b99b9f0cd4d6afe887d6Chris Banes context = new ContextThemeWrapper(context, 0); 150357c6de90985a63358129b99b9f0cd4d6afe887d6Chris Banes context.getTheme().setTo(widgetTheme); 150457c6de90985a63358129b99b9f0cd4d6afe887d6Chris Banes 150557c6de90985a63358129b99b9f0cd4d6afe887d6Chris Banes listPresenterContext = context; 150600d183885b54de433e43118d3032340f40cac8c0Chris Banes } 150700d183885b54de433e43118d3032340f40cac8c0Chris Banes 150800d183885b54de433e43118d3032340f40cac8c0Chris Banes void setMenu(MenuBuilder menu) { 150900d183885b54de433e43118d3032340f40cac8c0Chris Banes if (menu == this.menu) return; 151000d183885b54de433e43118d3032340f40cac8c0Chris Banes 151100d183885b54de433e43118d3032340f40cac8c0Chris Banes if (this.menu != null) { 151200d183885b54de433e43118d3032340f40cac8c0Chris Banes this.menu.removeMenuPresenter(listMenuPresenter); 151300d183885b54de433e43118d3032340f40cac8c0Chris Banes } 151400d183885b54de433e43118d3032340f40cac8c0Chris Banes this.menu = menu; 151500d183885b54de433e43118d3032340f40cac8c0Chris Banes if (menu != null) { 151600d183885b54de433e43118d3032340f40cac8c0Chris Banes if (listMenuPresenter != null) menu.addMenuPresenter(listMenuPresenter); 151700d183885b54de433e43118d3032340f40cac8c0Chris Banes } 151800d183885b54de433e43118d3032340f40cac8c0Chris Banes } 151900d183885b54de433e43118d3032340f40cac8c0Chris Banes 152057c6de90985a63358129b99b9f0cd4d6afe887d6Chris Banes MenuView getListMenuView(MenuPresenter.Callback cb) { 152100d183885b54de433e43118d3032340f40cac8c0Chris Banes if (menu == null) return null; 152200d183885b54de433e43118d3032340f40cac8c0Chris Banes 152300d183885b54de433e43118d3032340f40cac8c0Chris Banes if (listMenuPresenter == null) { 152457c6de90985a63358129b99b9f0cd4d6afe887d6Chris Banes listMenuPresenter = new ListMenuPresenter(listPresenterContext, 152557c6de90985a63358129b99b9f0cd4d6afe887d6Chris Banes R.layout.abc_list_menu_item_layout); 152600d183885b54de433e43118d3032340f40cac8c0Chris Banes listMenuPresenter.setCallback(cb); 152700d183885b54de433e43118d3032340f40cac8c0Chris Banes menu.addMenuPresenter(listMenuPresenter); 152800d183885b54de433e43118d3032340f40cac8c0Chris Banes } 152900d183885b54de433e43118d3032340f40cac8c0Chris Banes 153000d183885b54de433e43118d3032340f40cac8c0Chris Banes MenuView result = listMenuPresenter.getMenuView(decorView); 153100d183885b54de433e43118d3032340f40cac8c0Chris Banes 153200d183885b54de433e43118d3032340f40cac8c0Chris Banes return result; 153300d183885b54de433e43118d3032340f40cac8c0Chris Banes } 153400d183885b54de433e43118d3032340f40cac8c0Chris Banes 153500d183885b54de433e43118d3032340f40cac8c0Chris Banes Parcelable onSaveInstanceState() { 153600d183885b54de433e43118d3032340f40cac8c0Chris Banes SavedState savedState = new SavedState(); 153700d183885b54de433e43118d3032340f40cac8c0Chris Banes savedState.featureId = featureId; 153800d183885b54de433e43118d3032340f40cac8c0Chris Banes savedState.isOpen = isOpen; 153900d183885b54de433e43118d3032340f40cac8c0Chris Banes 154000d183885b54de433e43118d3032340f40cac8c0Chris Banes if (menu != null) { 154100d183885b54de433e43118d3032340f40cac8c0Chris Banes savedState.menuState = new Bundle(); 154200d183885b54de433e43118d3032340f40cac8c0Chris Banes menu.savePresenterStates(savedState.menuState); 154300d183885b54de433e43118d3032340f40cac8c0Chris Banes } 154400d183885b54de433e43118d3032340f40cac8c0Chris Banes 154500d183885b54de433e43118d3032340f40cac8c0Chris Banes return savedState; 154600d183885b54de433e43118d3032340f40cac8c0Chris Banes } 154700d183885b54de433e43118d3032340f40cac8c0Chris Banes 154800d183885b54de433e43118d3032340f40cac8c0Chris Banes void onRestoreInstanceState(Parcelable state) { 154900d183885b54de433e43118d3032340f40cac8c0Chris Banes SavedState savedState = (SavedState) state; 155000d183885b54de433e43118d3032340f40cac8c0Chris Banes featureId = savedState.featureId; 155100d183885b54de433e43118d3032340f40cac8c0Chris Banes wasLastOpen = savedState.isOpen; 155200d183885b54de433e43118d3032340f40cac8c0Chris Banes frozenMenuState = savedState.menuState; 155300d183885b54de433e43118d3032340f40cac8c0Chris Banes 155400d183885b54de433e43118d3032340f40cac8c0Chris Banes shownPanelView = null; 155500d183885b54de433e43118d3032340f40cac8c0Chris Banes decorView = null; 155600d183885b54de433e43118d3032340f40cac8c0Chris Banes } 155700d183885b54de433e43118d3032340f40cac8c0Chris Banes 155800d183885b54de433e43118d3032340f40cac8c0Chris Banes void applyFrozenState() { 155900d183885b54de433e43118d3032340f40cac8c0Chris Banes if (menu != null && frozenMenuState != null) { 156000d183885b54de433e43118d3032340f40cac8c0Chris Banes menu.restorePresenterStates(frozenMenuState); 156100d183885b54de433e43118d3032340f40cac8c0Chris Banes frozenMenuState = null; 156200d183885b54de433e43118d3032340f40cac8c0Chris Banes } 156300d183885b54de433e43118d3032340f40cac8c0Chris Banes } 156400d183885b54de433e43118d3032340f40cac8c0Chris Banes 156500d183885b54de433e43118d3032340f40cac8c0Chris Banes private static class SavedState implements Parcelable { 156600d183885b54de433e43118d3032340f40cac8c0Chris Banes int featureId; 156700d183885b54de433e43118d3032340f40cac8c0Chris Banes boolean isOpen; 156800d183885b54de433e43118d3032340f40cac8c0Chris Banes Bundle menuState; 156900d183885b54de433e43118d3032340f40cac8c0Chris Banes 157000d183885b54de433e43118d3032340f40cac8c0Chris Banes public int describeContents() { 157100d183885b54de433e43118d3032340f40cac8c0Chris Banes return 0; 157200d183885b54de433e43118d3032340f40cac8c0Chris Banes } 157300d183885b54de433e43118d3032340f40cac8c0Chris Banes 157400d183885b54de433e43118d3032340f40cac8c0Chris Banes public void writeToParcel(Parcel dest, int flags) { 157500d183885b54de433e43118d3032340f40cac8c0Chris Banes dest.writeInt(featureId); 157600d183885b54de433e43118d3032340f40cac8c0Chris Banes dest.writeInt(isOpen ? 1 : 0); 157700d183885b54de433e43118d3032340f40cac8c0Chris Banes 157800d183885b54de433e43118d3032340f40cac8c0Chris Banes if (isOpen) { 157900d183885b54de433e43118d3032340f40cac8c0Chris Banes dest.writeBundle(menuState); 158000d183885b54de433e43118d3032340f40cac8c0Chris Banes } 158100d183885b54de433e43118d3032340f40cac8c0Chris Banes } 158200d183885b54de433e43118d3032340f40cac8c0Chris Banes 158300d183885b54de433e43118d3032340f40cac8c0Chris Banes private static SavedState readFromParcel(Parcel source) { 158400d183885b54de433e43118d3032340f40cac8c0Chris Banes SavedState savedState = new SavedState(); 158500d183885b54de433e43118d3032340f40cac8c0Chris Banes savedState.featureId = source.readInt(); 158600d183885b54de433e43118d3032340f40cac8c0Chris Banes savedState.isOpen = source.readInt() == 1; 158700d183885b54de433e43118d3032340f40cac8c0Chris Banes 158800d183885b54de433e43118d3032340f40cac8c0Chris Banes if (savedState.isOpen) { 158900d183885b54de433e43118d3032340f40cac8c0Chris Banes savedState.menuState = source.readBundle(); 159000d183885b54de433e43118d3032340f40cac8c0Chris Banes } 159100d183885b54de433e43118d3032340f40cac8c0Chris Banes 159200d183885b54de433e43118d3032340f40cac8c0Chris Banes return savedState; 159300d183885b54de433e43118d3032340f40cac8c0Chris Banes } 159400d183885b54de433e43118d3032340f40cac8c0Chris Banes 159500d183885b54de433e43118d3032340f40cac8c0Chris Banes public static final Parcelable.Creator<SavedState> CREATOR 159600d183885b54de433e43118d3032340f40cac8c0Chris Banes = new Parcelable.Creator<SavedState>() { 159700d183885b54de433e43118d3032340f40cac8c0Chris Banes public SavedState createFromParcel(Parcel in) { 159800d183885b54de433e43118d3032340f40cac8c0Chris Banes return readFromParcel(in); 159900d183885b54de433e43118d3032340f40cac8c0Chris Banes } 160000d183885b54de433e43118d3032340f40cac8c0Chris Banes 160100d183885b54de433e43118d3032340f40cac8c0Chris Banes public SavedState[] newArray(int size) { 160200d183885b54de433e43118d3032340f40cac8c0Chris Banes return new SavedState[size]; 160300d183885b54de433e43118d3032340f40cac8c0Chris Banes } 160400d183885b54de433e43118d3032340f40cac8c0Chris Banes }; 160503fc11b659da1645507062bddda450136e13af35Chris Banes } 160603fc11b659da1645507062bddda450136e13af35Chris Banes } 160703fc11b659da1645507062bddda450136e13af35Chris Banes 16086386aac7ea9be44d23dcea28d9a02110c174e988Chris Banes} 1609