blob: db20549ee5ae78057a2ba51b14950739b7285a18 [file] [log] [blame]
Adam Powell89e06452010-06-23 20:24:52 -07001/*
2 * Copyright (C) 2010 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package com.android.internal.app;
18
Adam Powellb8139af2012-04-19 13:52:46 -070019import com.android.internal.view.ActionBarPolicy;
Adam Powell2c9c9fe2010-07-16 10:17:57 -070020import com.android.internal.view.menu.MenuBuilder;
Adam Powell2c9c9fe2010-07-16 10:17:57 -070021import com.android.internal.view.menu.MenuPopupHelper;
22import com.android.internal.view.menu.SubMenuBuilder;
Adam Powell01feaee2011-02-10 15:05:05 -080023import com.android.internal.widget.ActionBarContainer;
Adam Powell89e06452010-06-23 20:24:52 -070024import com.android.internal.widget.ActionBarContextView;
Dianne Hackborn3a3a6cf2012-03-26 10:24:04 -070025import com.android.internal.widget.ActionBarOverlayLayout;
Adam Powell89e06452010-06-23 20:24:52 -070026import com.android.internal.widget.ActionBarView;
Adam Powellf8ac6b72011-05-23 18:14:09 -070027import com.android.internal.widget.ScrollingTabContainerView;
Adam Powell89e06452010-06-23 20:24:52 -070028
Adam Powelld8b3f2e2010-12-02 13:37:03 -080029import android.animation.Animator;
Adam Powelld8b3f2e2010-12-02 13:37:03 -080030import android.animation.Animator.AnimatorListener;
Adam Powell07e1f982011-03-24 11:11:15 -070031import android.animation.AnimatorListenerAdapter;
Adam Powelld8b3f2e2010-12-02 13:37:03 -080032import android.animation.AnimatorSet;
Adam Powelle6ec7322010-12-07 15:29:26 -080033import android.animation.ObjectAnimator;
Adam Powell89e06452010-06-23 20:24:52 -070034import android.app.ActionBar;
Adam Powell661c9082010-07-02 10:09:44 -070035import android.app.Activity;
Adam Powelldec9dfd2010-08-09 15:27:54 -070036import android.app.Dialog;
Adam Powell661c9082010-07-02 10:09:44 -070037import android.app.FragmentTransaction;
Adam Powelldec9dfd2010-08-09 15:27:54 -070038import android.content.Context;
Adam Powellf8ac6b72011-05-23 18:14:09 -070039import android.content.res.Configuration;
Adam Powell88ab6972011-07-28 11:25:01 -070040import android.content.res.Resources;
Adam Powell89e06452010-06-23 20:24:52 -070041import android.graphics.drawable.Drawable;
Adam Powell0e94b512010-06-29 17:58:20 -070042import android.os.Handler;
Dianne Hackborn139e5aa2012-05-05 20:36:38 -070043import android.util.Log;
Adam Powell88ab6972011-07-28 11:25:01 -070044import android.util.TypedValue;
Adam Powell6e346362010-07-23 10:18:23 -070045import android.view.ActionMode;
Adam Powell88ab6972011-07-28 11:25:01 -070046import android.view.ContextThemeWrapper;
Adam Powell32555f32010-11-17 13:49:22 -080047import android.view.LayoutInflater;
Adam Powell89e06452010-06-23 20:24:52 -070048import android.view.Menu;
Adam Powell9168f0b2010-08-02 15:46:24 -070049import android.view.MenuInflater;
Adam Powell89e06452010-06-23 20:24:52 -070050import android.view.MenuItem;
51import android.view.View;
Dianne Hackborn3a3a6cf2012-03-26 10:24:04 -070052import android.view.ViewGroup;
Adam Powelle6ec7322010-12-07 15:29:26 -080053import android.view.Window;
Adam Powell86ed4362011-09-14 16:18:53 -070054import android.view.accessibility.AccessibilityEvent;
Dianne Hackborn8eedb8b2012-04-16 19:31:58 -070055import android.view.animation.AnimationUtils;
Adam Powell89e06452010-06-23 20:24:52 -070056import android.widget.SpinnerAdapter;
Adam Powell89e06452010-06-23 20:24:52 -070057
Adam Powell29ed7572010-07-14 16:24:56 -070058import java.lang.ref.WeakReference;
Adam Powell661c9082010-07-02 10:09:44 -070059import java.util.ArrayList;
60
Adam Powell89e06452010-06-23 20:24:52 -070061/**
62 * ActionBarImpl is the ActionBar implementation used
63 * by devices of all screen sizes. If it detects a compatible decor,
64 * it will split contextual modes across both the ActionBarView at
65 * the top of the screen and a horizontal LinearLayout at the bottom
66 * which is normally hidden.
67 */
68public class ActionBarImpl extends ActionBar {
Adam Powelld8145042011-03-24 14:18:27 -070069 private static final String TAG = "ActionBarImpl";
Adam Powell661c9082010-07-02 10:09:44 -070070
Adam Powelldec9dfd2010-08-09 15:27:54 -070071 private Context mContext;
Adam Powell88ab6972011-07-28 11:25:01 -070072 private Context mThemedContext;
Adam Powell661c9082010-07-02 10:09:44 -070073 private Activity mActivity;
Adam Powelldec9dfd2010-08-09 15:27:54 -070074 private Dialog mDialog;
Adam Powell661c9082010-07-02 10:09:44 -070075
Dianne Hackborn3a3a6cf2012-03-26 10:24:04 -070076 private ActionBarOverlayLayout mOverlayLayout;
Adam Powell01feaee2011-02-10 15:05:05 -080077 private ActionBarContainer mContainerView;
Dianne Hackborn3a3a6cf2012-03-26 10:24:04 -070078 private ViewGroup mTopVisibilityView;
Adam Powell89e06452010-06-23 20:24:52 -070079 private ActionBarView mActionView;
Adam Powell640a66e2011-04-29 10:18:53 -070080 private ActionBarContextView mContextView;
81 private ActionBarContainer mSplitView;
Adam Powelle6ec7322010-12-07 15:29:26 -080082 private View mContentView;
Adam Powellf8ac6b72011-05-23 18:14:09 -070083 private ScrollingTabContainerView mTabScrollView;
Adam Powell661c9082010-07-02 10:09:44 -070084
85 private ArrayList<TabImpl> mTabs = new ArrayList<TabImpl>();
86
Adam Powell661c9082010-07-02 10:09:44 -070087 private TabImpl mSelectedTab;
Adam Powell0c24a552010-11-03 16:44:11 -070088 private int mSavedTabPosition = INVALID_POSITION;
Adam Powell89e06452010-06-23 20:24:52 -070089
Adam Powelldd8fab22012-03-22 17:47:27 -070090 private boolean mDisplayHomeAsUpSet;
91
Adam Powell060e3ca2011-07-19 20:39:16 -070092 ActionModeImpl mActionMode;
93 ActionMode mDeferredDestroyActionMode;
94 ActionMode.Callback mDeferredModeDestroyCallback;
Adam Powell89e06452010-06-23 20:24:52 -070095
Adam Powell8515ee82010-11-30 14:09:55 -080096 private boolean mLastMenuVisibility;
97 private ArrayList<OnMenuVisibilityListener> mMenuVisibilityListeners =
98 new ArrayList<OnMenuVisibilityListener>();
99
Adam Powell89e06452010-06-23 20:24:52 -0700100 private static final int CONTEXT_DISPLAY_NORMAL = 0;
101 private static final int CONTEXT_DISPLAY_SPLIT = 1;
102
Adam Powell0c24a552010-11-03 16:44:11 -0700103 private static final int INVALID_POSITION = -1;
104
Adam Powell89e06452010-06-23 20:24:52 -0700105 private int mContextDisplayMode;
Adam Powellf8ac6b72011-05-23 18:14:09 -0700106 private boolean mHasEmbeddedTabs;
Adam Powell0e94b512010-06-29 17:58:20 -0700107
108 final Handler mHandler = new Handler();
Adam Powellf8ac6b72011-05-23 18:14:09 -0700109 Runnable mTabSelector;
Adam Powelld8b3f2e2010-12-02 13:37:03 -0800110
Dianne Hackborn3a3a6cf2012-03-26 10:24:04 -0700111 private int mCurWindowVisibility = View.VISIBLE;
112
Dianne Hackborndf7221c2013-02-26 14:53:55 -0800113 private boolean mContentAnimations = true;
Dianne Hackborn139e5aa2012-05-05 20:36:38 -0700114 private boolean mHiddenByApp;
115 private boolean mHiddenBySystem;
116 private boolean mShowingForMode;
117
118 private boolean mNowShowing = true;
119
Adam Powell07e1f982011-03-24 11:11:15 -0700120 private Animator mCurrentShowAnim;
Adam Powell50efbed2011-02-08 16:20:15 -0800121 private boolean mShowHideAnimationEnabled;
Adam Powelld8b3f2e2010-12-02 13:37:03 -0800122
Adam Powell07e1f982011-03-24 11:11:15 -0700123 final AnimatorListener mHideListener = new AnimatorListenerAdapter() {
Adam Powelle6ec7322010-12-07 15:29:26 -0800124 @Override
125 public void onAnimationEnd(Animator animation) {
Dianne Hackborndf7221c2013-02-26 14:53:55 -0800126 if (mContentAnimations && mContentView != null) {
Adam Powelle6ec7322010-12-07 15:29:26 -0800127 mContentView.setTranslationY(0);
Dianne Hackborn3a3a6cf2012-03-26 10:24:04 -0700128 mTopVisibilityView.setTranslationY(0);
Adam Powelle6ec7322010-12-07 15:29:26 -0800129 }
Adam Powell993a63a2011-08-18 16:35:53 -0700130 if (mSplitView != null && mContextDisplayMode == CONTEXT_DISPLAY_SPLIT) {
131 mSplitView.setVisibility(View.GONE);
132 }
Dianne Hackborn3a3a6cf2012-03-26 10:24:04 -0700133 mTopVisibilityView.setVisibility(View.GONE);
Adam Powell01feaee2011-02-10 15:05:05 -0800134 mContainerView.setTransitioning(false);
Adam Powell07e1f982011-03-24 11:11:15 -0700135 mCurrentShowAnim = null;
Adam Powell060e3ca2011-07-19 20:39:16 -0700136 completeDeferredDestroyActionMode();
Dianne Hackborn139e5aa2012-05-05 20:36:38 -0700137 if (mOverlayLayout != null) {
138 mOverlayLayout.requestFitSystemWindows();
139 }
Adam Powelle6ec7322010-12-07 15:29:26 -0800140 }
141 };
142
Adam Powell07e1f982011-03-24 11:11:15 -0700143 final AnimatorListener mShowListener = new AnimatorListenerAdapter() {
Adam Powelle6ec7322010-12-07 15:29:26 -0800144 @Override
145 public void onAnimationEnd(Animator animation) {
Adam Powell07e1f982011-03-24 11:11:15 -0700146 mCurrentShowAnim = null;
Dianne Hackborn3a3a6cf2012-03-26 10:24:04 -0700147 mTopVisibilityView.requestLayout();
Adam Powelle6ec7322010-12-07 15:29:26 -0800148 }
Adam Powelle6ec7322010-12-07 15:29:26 -0800149 };
150
Adam Powell661c9082010-07-02 10:09:44 -0700151 public ActionBarImpl(Activity activity) {
Adam Powell661c9082010-07-02 10:09:44 -0700152 mActivity = activity;
Adam Powelle6ec7322010-12-07 15:29:26 -0800153 Window window = activity.getWindow();
154 View decor = window.getDecorView();
Dianne Hackborndf7221c2013-02-26 14:53:55 -0800155 boolean overlayMode = mActivity.getWindow().hasFeature(Window.FEATURE_ACTION_BAR_OVERLAY);
156 init(decor, overlayMode);
157 if (!overlayMode) {
Adam Powelle6ec7322010-12-07 15:29:26 -0800158 mContentView = decor.findViewById(android.R.id.content);
159 }
Adam Powelldec9dfd2010-08-09 15:27:54 -0700160 }
161
162 public ActionBarImpl(Dialog dialog) {
163 mDialog = dialog;
Dianne Hackborndf7221c2013-02-26 14:53:55 -0800164 init(dialog.getWindow().getDecorView(), false);
Adam Powelldec9dfd2010-08-09 15:27:54 -0700165 }
166
Dianne Hackborndf7221c2013-02-26 14:53:55 -0800167 private void init(View decor, boolean overlayMode) {
Adam Powelldec9dfd2010-08-09 15:27:54 -0700168 mContext = decor.getContext();
Dianne Hackborn3a3a6cf2012-03-26 10:24:04 -0700169 mOverlayLayout = (ActionBarOverlayLayout) decor.findViewById(
170 com.android.internal.R.id.action_bar_overlay_layout);
171 if (mOverlayLayout != null) {
Dianne Hackborndf7221c2013-02-26 14:53:55 -0800172 mOverlayLayout.setActionBar(this, overlayMode);
Dianne Hackborn3a3a6cf2012-03-26 10:24:04 -0700173 }
Adam Powell89e06452010-06-23 20:24:52 -0700174 mActionView = (ActionBarView) decor.findViewById(com.android.internal.R.id.action_bar);
Adam Powell640a66e2011-04-29 10:18:53 -0700175 mContextView = (ActionBarContextView) decor.findViewById(
Adam Powell89e06452010-06-23 20:24:52 -0700176 com.android.internal.R.id.action_context_bar);
Adam Powell01feaee2011-02-10 15:05:05 -0800177 mContainerView = (ActionBarContainer) decor.findViewById(
Adam Powelld8b3f2e2010-12-02 13:37:03 -0800178 com.android.internal.R.id.action_bar_container);
Dianne Hackborn3a3a6cf2012-03-26 10:24:04 -0700179 mTopVisibilityView = (ViewGroup)decor.findViewById(
180 com.android.internal.R.id.top_action_bar);
181 if (mTopVisibilityView == null) {
182 mTopVisibilityView = mContainerView;
183 }
Adam Powell640a66e2011-04-29 10:18:53 -0700184 mSplitView = (ActionBarContainer) decor.findViewById(
185 com.android.internal.R.id.split_action_bar);
Steve Block08f194b2010-08-24 18:20:48 +0100186
Adam Powell640a66e2011-04-29 10:18:53 -0700187 if (mActionView == null || mContextView == null || mContainerView == null) {
Adam Powell89e06452010-06-23 20:24:52 -0700188 throw new IllegalStateException(getClass().getSimpleName() + " can only be used " +
189 "with a compatible window decor layout");
190 }
Adam Powell0e94b512010-06-29 17:58:20 -0700191
Adam Powell640a66e2011-04-29 10:18:53 -0700192 mActionView.setContextView(mContextView);
Adam Powell9b4bee02011-04-27 19:24:47 -0700193 mContextDisplayMode = mActionView.isSplitActionBar() ?
194 CONTEXT_DISPLAY_SPLIT : CONTEXT_DISPLAY_NORMAL;
Adam Powelldae78242011-04-25 15:23:41 -0700195
Adam Powelld40423a2012-05-02 14:06:03 -0700196 // This was initially read from the action bar style
197 final int current = mActionView.getDisplayOptions();
198 final boolean homeAsUp = (current & DISPLAY_HOME_AS_UP) != 0;
199 if (homeAsUp) {
200 mDisplayHomeAsUpSet = true;
201 }
202
Adam Powellb8139af2012-04-19 13:52:46 -0700203 ActionBarPolicy abp = ActionBarPolicy.get(mContext);
Adam Powelld40423a2012-05-02 14:06:03 -0700204 setHomeButtonEnabled(abp.enableHomeButtonByDefault() || homeAsUp);
Adam Powellb8139af2012-04-19 13:52:46 -0700205 setHasEmbeddedTabs(abp.hasEmbeddedTabs());
Adam Powellf8ac6b72011-05-23 18:14:09 -0700206 }
207
208 public void onConfigurationChanged(Configuration newConfig) {
Adam Powellb8139af2012-04-19 13:52:46 -0700209 setHasEmbeddedTabs(ActionBarPolicy.get(mContext).hasEmbeddedTabs());
Adam Powellf5645cb2011-08-10 22:49:02 -0700210 }
Adam Powellf8ac6b72011-05-23 18:14:09 -0700211
Adam Powellf5645cb2011-08-10 22:49:02 -0700212 private void setHasEmbeddedTabs(boolean hasEmbeddedTabs) {
213 mHasEmbeddedTabs = hasEmbeddedTabs;
Adam Powellf8ac6b72011-05-23 18:14:09 -0700214 // Switch tab layout configuration if needed
215 if (!mHasEmbeddedTabs) {
216 mActionView.setEmbeddedTabView(null);
217 mContainerView.setTabContainer(mTabScrollView);
218 } else {
219 mContainerView.setTabContainer(null);
Adam Powellf8ac6b72011-05-23 18:14:09 -0700220 mActionView.setEmbeddedTabView(mTabScrollView);
221 }
Adam Powellf5645cb2011-08-10 22:49:02 -0700222 final boolean isInTabMode = getNavigationMode() == NAVIGATION_MODE_TABS;
223 if (mTabScrollView != null) {
Dianne Hackborn3a3a6cf2012-03-26 10:24:04 -0700224 if (isInTabMode) {
225 mTabScrollView.setVisibility(View.VISIBLE);
226 if (mOverlayLayout != null) {
227 mOverlayLayout.requestFitSystemWindows();
228 }
229 } else {
230 mTabScrollView.setVisibility(View.GONE);
231 }
Adam Powellf5645cb2011-08-10 22:49:02 -0700232 }
233 mActionView.setCollapsable(!mHasEmbeddedTabs && isInTabMode);
Adam Powellf8ac6b72011-05-23 18:14:09 -0700234 }
235
Dianne Hackborn3a3a6cf2012-03-26 10:24:04 -0700236 public boolean hasNonEmbeddedTabs() {
237 return !mHasEmbeddedTabs && getNavigationMode() == NAVIGATION_MODE_TABS;
238 }
239
Adam Powellf8ac6b72011-05-23 18:14:09 -0700240 private void ensureTabsExist() {
241 if (mTabScrollView != null) {
242 return;
243 }
244
Adam Powellf5645cb2011-08-10 22:49:02 -0700245 ScrollingTabContainerView tabScroller = new ScrollingTabContainerView(mContext);
Adam Powellf8ac6b72011-05-23 18:14:09 -0700246
247 if (mHasEmbeddedTabs) {
248 tabScroller.setVisibility(View.VISIBLE);
249 mActionView.setEmbeddedTabView(tabScroller);
250 } else {
Dianne Hackborn3a3a6cf2012-03-26 10:24:04 -0700251 if (getNavigationMode() == NAVIGATION_MODE_TABS) {
252 tabScroller.setVisibility(View.VISIBLE);
253 if (mOverlayLayout != null) {
254 mOverlayLayout.requestFitSystemWindows();
255 }
256 } else {
257 tabScroller.setVisibility(View.GONE);
258 }
Adam Powelldae78242011-04-25 15:23:41 -0700259 mContainerView.setTabContainer(tabScroller);
Adam Powelldae78242011-04-25 15:23:41 -0700260 }
Adam Powellf8ac6b72011-05-23 18:14:09 -0700261 mTabScrollView = tabScroller;
Adam Powell89e06452010-06-23 20:24:52 -0700262 }
263
Adam Powell060e3ca2011-07-19 20:39:16 -0700264 void completeDeferredDestroyActionMode() {
265 if (mDeferredModeDestroyCallback != null) {
266 mDeferredModeDestroyCallback.onDestroyActionMode(mDeferredDestroyActionMode);
267 mDeferredDestroyActionMode = null;
268 mDeferredModeDestroyCallback = null;
269 }
270 }
271
Dianne Hackborn3a3a6cf2012-03-26 10:24:04 -0700272 public void setWindowVisibility(int visibility) {
273 mCurWindowVisibility = visibility;
274 }
275
Adam Powell50efbed2011-02-08 16:20:15 -0800276 /**
277 * Enables or disables animation between show/hide states.
278 * If animation is disabled using this method, animations in progress
279 * will be finished.
280 *
281 * @param enabled true to animate, false to not animate.
282 */
283 public void setShowHideAnimationEnabled(boolean enabled) {
284 mShowHideAnimationEnabled = enabled;
Adam Powell07e1f982011-03-24 11:11:15 -0700285 if (!enabled && mCurrentShowAnim != null) {
286 mCurrentShowAnim.end();
Adam Powell50efbed2011-02-08 16:20:15 -0800287 }
288 }
289
Adam Powell8515ee82010-11-30 14:09:55 -0800290 public void addOnMenuVisibilityListener(OnMenuVisibilityListener listener) {
291 mMenuVisibilityListeners.add(listener);
292 }
293
294 public void removeOnMenuVisibilityListener(OnMenuVisibilityListener listener) {
295 mMenuVisibilityListeners.remove(listener);
296 }
297
298 public void dispatchMenuVisibilityChanged(boolean isVisible) {
299 if (isVisible == mLastMenuVisibility) {
300 return;
301 }
302 mLastMenuVisibility = isVisible;
303
304 final int count = mMenuVisibilityListeners.size();
305 for (int i = 0; i < count; i++) {
306 mMenuVisibilityListeners.get(i).onMenuVisibilityChanged(isVisible);
307 }
308 }
309
Adam Powella66c7b02010-07-28 15:28:25 -0700310 @Override
Adam Powell3f476b32011-01-03 19:25:36 -0800311 public void setCustomView(int resId) {
Adam Powellf2423682011-08-11 14:29:45 -0700312 setCustomView(LayoutInflater.from(getThemedContext()).inflate(resId, mActionView, false));
Adam Powell3f476b32011-01-03 19:25:36 -0800313 }
314
315 @Override
316 public void setDisplayUseLogoEnabled(boolean useLogo) {
317 setDisplayOptions(useLogo ? DISPLAY_USE_LOGO : 0, DISPLAY_USE_LOGO);
318 }
319
320 @Override
321 public void setDisplayShowHomeEnabled(boolean showHome) {
322 setDisplayOptions(showHome ? DISPLAY_SHOW_HOME : 0, DISPLAY_SHOW_HOME);
323 }
324
325 @Override
326 public void setDisplayHomeAsUpEnabled(boolean showHomeAsUp) {
327 setDisplayOptions(showHomeAsUp ? DISPLAY_HOME_AS_UP : 0, DISPLAY_HOME_AS_UP);
328 }
329
330 @Override
331 public void setDisplayShowTitleEnabled(boolean showTitle) {
332 setDisplayOptions(showTitle ? DISPLAY_SHOW_TITLE : 0, DISPLAY_SHOW_TITLE);
333 }
334
335 @Override
336 public void setDisplayShowCustomEnabled(boolean showCustom) {
337 setDisplayOptions(showCustom ? DISPLAY_SHOW_CUSTOM : 0, DISPLAY_SHOW_CUSTOM);
338 }
339
340 @Override
Adam Powellc29f4e52011-07-13 20:40:52 -0700341 public void setHomeButtonEnabled(boolean enable) {
342 mActionView.setHomeButtonEnabled(enable);
Adam Powelldae78242011-04-25 15:23:41 -0700343 }
344
345 @Override
Adam Powella66c7b02010-07-28 15:28:25 -0700346 public void setTitle(int resId) {
Adam Powelldec9dfd2010-08-09 15:27:54 -0700347 setTitle(mContext.getString(resId));
Adam Powella66c7b02010-07-28 15:28:25 -0700348 }
349
350 @Override
351 public void setSubtitle(int resId) {
Adam Powelldec9dfd2010-08-09 15:27:54 -0700352 setSubtitle(mContext.getString(resId));
Adam Powella66c7b02010-07-28 15:28:25 -0700353 }
354
Adam Powell17809772010-07-21 13:25:11 -0700355 public void setSelectedNavigationItem(int position) {
356 switch (mActionView.getNavigationMode()) {
357 case NAVIGATION_MODE_TABS:
358 selectTab(mTabs.get(position));
359 break;
Adam Powell9ab97872010-10-26 21:47:29 -0700360 case NAVIGATION_MODE_LIST:
Adam Powell17809772010-07-21 13:25:11 -0700361 mActionView.setDropdownSelectedPosition(position);
362 break;
363 default:
364 throw new IllegalStateException(
Adam Powell9ab97872010-10-26 21:47:29 -0700365 "setSelectedNavigationIndex not valid for current navigation mode");
Adam Powell17809772010-07-21 13:25:11 -0700366 }
367 }
368
Adam Powell9ab97872010-10-26 21:47:29 -0700369 public void removeAllTabs() {
370 cleanupTabs();
Adam Powell17809772010-07-21 13:25:11 -0700371 }
372
Adam Powell661c9082010-07-02 10:09:44 -0700373 private void cleanupTabs() {
374 if (mSelectedTab != null) {
375 selectTab(null);
376 }
Adam Powell2b6230e2010-09-07 17:55:25 -0700377 mTabs.clear();
Adam Powelld21aa122011-05-27 13:09:52 -0700378 if (mTabScrollView != null) {
379 mTabScrollView.removeAllTabs();
380 }
Adam Powell0c24a552010-11-03 16:44:11 -0700381 mSavedTabPosition = INVALID_POSITION;
Adam Powell661c9082010-07-02 10:09:44 -0700382 }
383
Adam Powell0e94b512010-06-29 17:58:20 -0700384 public void setTitle(CharSequence title) {
385 mActionView.setTitle(title);
386 }
387
388 public void setSubtitle(CharSequence subtitle) {
389 mActionView.setSubtitle(subtitle);
390 }
391
Adam Powell89e06452010-06-23 20:24:52 -0700392 public void setDisplayOptions(int options) {
Adam Powelldd8fab22012-03-22 17:47:27 -0700393 if ((options & DISPLAY_HOME_AS_UP) != 0) {
394 mDisplayHomeAsUpSet = true;
395 }
Adam Powell89e06452010-06-23 20:24:52 -0700396 mActionView.setDisplayOptions(options);
397 }
Adam Powell0e94b512010-06-29 17:58:20 -0700398
Adam Powell89e06452010-06-23 20:24:52 -0700399 public void setDisplayOptions(int options, int mask) {
400 final int current = mActionView.getDisplayOptions();
Adam Powelldd8fab22012-03-22 17:47:27 -0700401 if ((mask & DISPLAY_HOME_AS_UP) != 0) {
402 mDisplayHomeAsUpSet = true;
403 }
Adam Powell89e06452010-06-23 20:24:52 -0700404 mActionView.setDisplayOptions((options & mask) | (current & ~mask));
405 }
406
407 public void setBackgroundDrawable(Drawable d) {
Adam Powellf88b9152011-09-07 14:54:32 -0700408 mContainerView.setPrimaryBackground(d);
409 }
410
411 public void setStackedBackgroundDrawable(Drawable d) {
412 mContainerView.setStackedBackground(d);
413 }
414
415 public void setSplitBackgroundDrawable(Drawable d) {
416 if (mSplitView != null) {
417 mSplitView.setSplitBackground(d);
418 }
Adam Powell89e06452010-06-23 20:24:52 -0700419 }
420
Adam Powellef704442010-11-16 14:48:22 -0800421 public View getCustomView() {
Adam Powell89e06452010-06-23 20:24:52 -0700422 return mActionView.getCustomNavigationView();
423 }
424
425 public CharSequence getTitle() {
426 return mActionView.getTitle();
427 }
428
429 public CharSequence getSubtitle() {
430 return mActionView.getSubtitle();
431 }
432
433 public int getNavigationMode() {
434 return mActionView.getNavigationMode();
435 }
436
437 public int getDisplayOptions() {
438 return mActionView.getDisplayOptions();
439 }
440
Adam Powell5d279772010-07-27 16:34:07 -0700441 public ActionMode startActionMode(ActionMode.Callback callback) {
442 if (mActionMode != null) {
443 mActionMode.finish();
Adam Powell6e346362010-07-23 10:18:23 -0700444 }
Adam Powell3461b322010-07-14 11:34:43 -0700445
Adam Powell640a66e2011-04-29 10:18:53 -0700446 mContextView.killMode();
Adam Powell5ee36c42011-06-02 12:59:43 -0700447 ActionModeImpl mode = new ActionModeImpl(callback);
448 if (mode.dispatchOnCreate()) {
Adam Powell2c9c9fe2010-07-16 10:17:57 -0700449 mode.invalidate();
Adam Powell640a66e2011-04-29 10:18:53 -0700450 mContextView.initForMode(mode);
451 animateToMode(true);
Adam Powell1ab418a2011-06-09 20:49:49 -0700452 if (mSplitView != null && mContextDisplayMode == CONTEXT_DISPLAY_SPLIT) {
Adam Powell89e06452010-06-23 20:24:52 -0700453 // TODO animate this
Dianne Hackborn3a3a6cf2012-03-26 10:24:04 -0700454 if (mSplitView.getVisibility() != View.VISIBLE) {
455 mSplitView.setVisibility(View.VISIBLE);
456 if (mOverlayLayout != null) {
457 mOverlayLayout.requestFitSystemWindows();
458 }
459 }
Adam Powell89e06452010-06-23 20:24:52 -0700460 }
Adam Powell86ed4362011-09-14 16:18:53 -0700461 mContextView.sendAccessibilityEvent(AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED);
Adam Powell5d279772010-07-27 16:34:07 -0700462 mActionMode = mode;
Adam Powellac695c62010-07-20 18:19:27 -0700463 return mode;
Adam Powell89e06452010-06-23 20:24:52 -0700464 }
Adam Powellac695c62010-07-20 18:19:27 -0700465 return null;
Adam Powell89e06452010-06-23 20:24:52 -0700466 }
467
Adam Powell661c9082010-07-02 10:09:44 -0700468 private void configureTab(Tab tab, int position) {
469 final TabImpl tabi = (TabImpl) tab;
Adam Powell2b6230e2010-09-07 17:55:25 -0700470 final ActionBar.TabListener callback = tabi.getCallback();
471
472 if (callback == null) {
473 throw new IllegalStateException("Action Bar Tab must have a Callback");
474 }
Adam Powell661c9082010-07-02 10:09:44 -0700475
476 tabi.setPosition(position);
477 mTabs.add(position, tabi);
478
Adam Powell81b89442010-11-02 17:58:56 -0700479 final int count = mTabs.size();
480 for (int i = position + 1; i < count; i++) {
481 mTabs.get(i).setPosition(i);
Adam Powell661c9082010-07-02 10:09:44 -0700482 }
Adam Powell661c9082010-07-02 10:09:44 -0700483 }
484
485 @Override
486 public void addTab(Tab tab) {
Adam Powell81b89442010-11-02 17:58:56 -0700487 addTab(tab, mTabs.isEmpty());
Adam Powell661c9082010-07-02 10:09:44 -0700488 }
489
490 @Override
Adam Powell2b6230e2010-09-07 17:55:25 -0700491 public void addTab(Tab tab, int position) {
Adam Powell81b89442010-11-02 17:58:56 -0700492 addTab(tab, position, mTabs.isEmpty());
493 }
494
495 @Override
496 public void addTab(Tab tab, boolean setSelected) {
Adam Powellf8ac6b72011-05-23 18:14:09 -0700497 ensureTabsExist();
498 mTabScrollView.addTab(tab, setSelected);
Adam Powell81b89442010-11-02 17:58:56 -0700499 configureTab(tab, mTabs.size());
500 if (setSelected) {
501 selectTab(tab);
502 }
503 }
504
505 @Override
506 public void addTab(Tab tab, int position, boolean setSelected) {
Adam Powellf8ac6b72011-05-23 18:14:09 -0700507 ensureTabsExist();
508 mTabScrollView.addTab(tab, position, setSelected);
Adam Powell661c9082010-07-02 10:09:44 -0700509 configureTab(tab, position);
Adam Powell81b89442010-11-02 17:58:56 -0700510 if (setSelected) {
511 selectTab(tab);
512 }
Adam Powell661c9082010-07-02 10:09:44 -0700513 }
514
515 @Override
516 public Tab newTab() {
517 return new TabImpl();
518 }
519
520 @Override
521 public void removeTab(Tab tab) {
522 removeTabAt(tab.getPosition());
523 }
524
525 @Override
526 public void removeTabAt(int position) {
Adam Powellf8ac6b72011-05-23 18:14:09 -0700527 if (mTabScrollView == null) {
528 // No tabs around to remove
529 return;
530 }
531
Adam Powell0c24a552010-11-03 16:44:11 -0700532 int selectedTabPosition = mSelectedTab != null
533 ? mSelectedTab.getPosition() : mSavedTabPosition;
Adam Powellf8ac6b72011-05-23 18:14:09 -0700534 mTabScrollView.removeTabAt(position);
Adam Powell0d8ec1d2011-05-03 14:49:13 -0700535 TabImpl removedTab = mTabs.remove(position);
536 if (removedTab != null) {
537 removedTab.setPosition(-1);
538 }
Adam Powell661c9082010-07-02 10:09:44 -0700539
540 final int newTabCount = mTabs.size();
541 for (int i = position; i < newTabCount; i++) {
542 mTabs.get(i).setPosition(i);
543 }
544
Adam Powell0c24a552010-11-03 16:44:11 -0700545 if (selectedTabPosition == position) {
546 selectTab(mTabs.isEmpty() ? null : mTabs.get(Math.max(0, position - 1)));
547 }
Adam Powell661c9082010-07-02 10:09:44 -0700548 }
549
550 @Override
Adam Powell661c9082010-07-02 10:09:44 -0700551 public void selectTab(Tab tab) {
Adam Powell0c24a552010-11-03 16:44:11 -0700552 if (getNavigationMode() != NAVIGATION_MODE_TABS) {
553 mSavedTabPosition = tab != null ? tab.getPosition() : INVALID_POSITION;
554 return;
555 }
556
Dianne Hackborn48e7b452011-01-17 12:28:35 -0800557 final FragmentTransaction trans = mActivity.getFragmentManager().beginTransaction()
Adam Powell0c24a552010-11-03 16:44:11 -0700558 .disallowAddToBackStack();
Adam Powell7f9b9052010-10-19 16:56:07 -0700559
560 if (mSelectedTab == tab) {
561 if (mSelectedTab != null) {
562 mSelectedTab.getCallback().onTabReselected(mSelectedTab, trans);
Adam Powellf8ac6b72011-05-23 18:14:09 -0700563 mTabScrollView.animateToTab(tab.getPosition());
Adam Powell7f9b9052010-10-19 16:56:07 -0700564 }
565 } else {
Adam Powellf8ac6b72011-05-23 18:14:09 -0700566 mTabScrollView.setTabSelected(tab != null ? tab.getPosition() : Tab.INVALID_POSITION);
Adam Powell7f9b9052010-10-19 16:56:07 -0700567 if (mSelectedTab != null) {
568 mSelectedTab.getCallback().onTabUnselected(mSelectedTab, trans);
569 }
570 mSelectedTab = (TabImpl) tab;
571 if (mSelectedTab != null) {
572 mSelectedTab.getCallback().onTabSelected(mSelectedTab, trans);
573 }
Adam Powell2b6230e2010-09-07 17:55:25 -0700574 }
575
576 if (!trans.isEmpty()) {
577 trans.commit();
578 }
579 }
580
581 @Override
582 public Tab getSelectedTab() {
583 return mSelectedTab;
Adam Powell661c9082010-07-02 10:09:44 -0700584 }
585
Adam Powell6b336f82010-08-10 20:13:01 -0700586 @Override
587 public int getHeight() {
Adam Powell58c5dc12011-07-14 21:08:10 -0700588 return mContainerView.getHeight();
Adam Powell6b336f82010-08-10 20:13:01 -0700589 }
590
Dianne Hackborndf7221c2013-02-26 14:53:55 -0800591 public void enableContentAnimations(boolean enabled) {
592 mContentAnimations = enabled;
593 }
594
Adam Powell6b336f82010-08-10 20:13:01 -0700595 @Override
596 public void show() {
Dianne Hackborn139e5aa2012-05-05 20:36:38 -0700597 if (mHiddenByApp) {
598 mHiddenByApp = false;
599 updateVisibility(false);
600 }
Adam Powell07e1f982011-03-24 11:11:15 -0700601 }
602
Dianne Hackborn139e5aa2012-05-05 20:36:38 -0700603 private void showForActionMode() {
604 if (!mShowingForMode) {
605 mShowingForMode = true;
606 if (mOverlayLayout != null) {
607 mOverlayLayout.setShowingForActionMode(true);
608 }
609 updateVisibility(false);
610 }
611 }
612
613 public void showForSystem() {
614 if (mHiddenBySystem) {
615 mHiddenBySystem = false;
616 updateVisibility(true);
617 }
618 }
619
620 @Override
621 public void hide() {
622 if (!mHiddenByApp) {
623 mHiddenByApp = true;
624 updateVisibility(false);
625 }
626 }
627
628 private void hideForActionMode() {
629 if (mShowingForMode) {
630 mShowingForMode = false;
631 if (mOverlayLayout != null) {
632 mOverlayLayout.setShowingForActionMode(false);
633 }
634 updateVisibility(false);
635 }
636 }
637
638 public void hideForSystem() {
639 if (!mHiddenBySystem) {
640 mHiddenBySystem = true;
641 updateVisibility(true);
642 }
643 }
644
645 private static boolean checkShowingFlags(boolean hiddenByApp, boolean hiddenBySystem,
646 boolean showingForMode) {
647 if (showingForMode) {
648 return true;
649 } else if (hiddenByApp || hiddenBySystem) {
650 return false;
651 } else {
652 return true;
653 }
654 }
655
656 private void updateVisibility(boolean fromSystem) {
657 // Based on the current state, should we be hidden or shown?
658 final boolean shown = checkShowingFlags(mHiddenByApp, mHiddenBySystem,
659 mShowingForMode);
660
661 if (shown) {
662 if (!mNowShowing) {
663 mNowShowing = true;
664 doShow(fromSystem);
665 }
666 } else {
667 if (mNowShowing) {
668 mNowShowing = false;
669 doHide(fromSystem);
670 }
671 }
672 }
673
674 public void doShow(boolean fromSystem) {
Adam Powell07e1f982011-03-24 11:11:15 -0700675 if (mCurrentShowAnim != null) {
676 mCurrentShowAnim.end();
Adam Powell45f1e082010-12-10 14:20:13 -0800677 }
Dianne Hackborn3a3a6cf2012-03-26 10:24:04 -0700678 mTopVisibilityView.setVisibility(View.VISIBLE);
Adam Powell50efbed2011-02-08 16:20:15 -0800679
Dianne Hackborn3a3a6cf2012-03-26 10:24:04 -0700680 if (mCurWindowVisibility == View.VISIBLE && (mShowHideAnimationEnabled
Dianne Hackborn139e5aa2012-05-05 20:36:38 -0700681 || fromSystem)) {
Chet Haasee8118e12012-05-30 14:19:02 -0700682 mTopVisibilityView.setTranslationY(0); // because we're about to ask its window loc
683 float startingY = -mTopVisibilityView.getHeight();
684 if (fromSystem) {
685 int topLeft[] = {0, 0};
686 mTopVisibilityView.getLocationInWindow(topLeft);
687 startingY -= topLeft[1];
688 }
689 mTopVisibilityView.setTranslationY(startingY);
Adam Powell50efbed2011-02-08 16:20:15 -0800690 AnimatorSet anim = new AnimatorSet();
Chet Haasee8118e12012-05-30 14:19:02 -0700691 AnimatorSet.Builder b = anim.play(ObjectAnimator.ofFloat(mTopVisibilityView,
692 "translationY", 0));
Dianne Hackborndf7221c2013-02-26 14:53:55 -0800693 if (mContentAnimations && mContentView != null) {
Adam Powell50efbed2011-02-08 16:20:15 -0800694 b.with(ObjectAnimator.ofFloat(mContentView, "translationY",
Chet Haasee8118e12012-05-30 14:19:02 -0700695 startingY, 0));
Adam Powell50efbed2011-02-08 16:20:15 -0800696 }
Adam Powell1ab418a2011-06-09 20:49:49 -0700697 if (mSplitView != null && mContextDisplayMode == CONTEXT_DISPLAY_SPLIT) {
Dianne Hackborn8eedb8b2012-04-16 19:31:58 -0700698 mSplitView.setTranslationY(mSplitView.getHeight());
Adam Powell993a63a2011-08-18 16:35:53 -0700699 mSplitView.setVisibility(View.VISIBLE);
Dianne Hackborn8eedb8b2012-04-16 19:31:58 -0700700 b.with(ObjectAnimator.ofFloat(mSplitView, "translationY", 0));
Adam Powell640a66e2011-04-29 10:18:53 -0700701 }
Dianne Hackborn8eedb8b2012-04-16 19:31:58 -0700702 anim.setInterpolator(AnimationUtils.loadInterpolator(mContext,
Chet Haasee8118e12012-05-30 14:19:02 -0700703 com.android.internal.R.interpolator.decelerate_cubic));
704 anim.setDuration(250);
Dianne Hackborn139e5aa2012-05-05 20:36:38 -0700705 // If this is being shown from the system, add a small delay.
706 // This is because we will also be animating in the status bar,
707 // and these two elements can't be done in lock-step. So we give
708 // a little time for the status bar to start its animation before
709 // the action bar animates. (This corresponds to the corresponding
710 // case when hiding, where the status bar has a small delay before
711 // starting.)
Adam Powell50efbed2011-02-08 16:20:15 -0800712 anim.addListener(mShowListener);
Adam Powell07e1f982011-03-24 11:11:15 -0700713 mCurrentShowAnim = anim;
Adam Powell50efbed2011-02-08 16:20:15 -0800714 anim.start();
715 } else {
Dianne Hackborn3a3a6cf2012-03-26 10:24:04 -0700716 mTopVisibilityView.setAlpha(1);
Dianne Hackborn80d55062012-05-22 18:03:20 -0700717 mTopVisibilityView.setTranslationY(0);
Dianne Hackborndf7221c2013-02-26 14:53:55 -0800718 if (mContentAnimations && mContentView != null) {
Dianne Hackborn80d55062012-05-22 18:03:20 -0700719 mContentView.setTranslationY(0);
720 }
721 if (mSplitView != null && mContextDisplayMode == CONTEXT_DISPLAY_SPLIT) {
722 mSplitView.setAlpha(1);
723 mSplitView.setTranslationY(0);
724 mSplitView.setVisibility(View.VISIBLE);
725 }
Adam Powell50efbed2011-02-08 16:20:15 -0800726 mShowListener.onAnimationEnd(null);
Adam Powelle6ec7322010-12-07 15:29:26 -0800727 }
Dianne Hackborn139e5aa2012-05-05 20:36:38 -0700728 if (mOverlayLayout != null) {
729 mOverlayLayout.requestFitSystemWindows();
730 }
Adam Powell6b336f82010-08-10 20:13:01 -0700731 }
732
Dianne Hackborn139e5aa2012-05-05 20:36:38 -0700733 public void doHide(boolean fromSystem) {
Adam Powell07e1f982011-03-24 11:11:15 -0700734 if (mCurrentShowAnim != null) {
735 mCurrentShowAnim.end();
Adam Powelle6ec7322010-12-07 15:29:26 -0800736 }
Adam Powell50efbed2011-02-08 16:20:15 -0800737
Dianne Hackborn3a3a6cf2012-03-26 10:24:04 -0700738 if (mCurWindowVisibility == View.VISIBLE && (mShowHideAnimationEnabled
Dianne Hackborn139e5aa2012-05-05 20:36:38 -0700739 || fromSystem)) {
Dianne Hackborn3a3a6cf2012-03-26 10:24:04 -0700740 mTopVisibilityView.setAlpha(1);
Adam Powell01feaee2011-02-10 15:05:05 -0800741 mContainerView.setTransitioning(true);
Adam Powell50efbed2011-02-08 16:20:15 -0800742 AnimatorSet anim = new AnimatorSet();
Chet Haasee8118e12012-05-30 14:19:02 -0700743 float endingY = -mTopVisibilityView.getHeight();
744 if (fromSystem) {
745 int topLeft[] = {0, 0};
746 mTopVisibilityView.getLocationInWindow(topLeft);
747 endingY -= topLeft[1];
748 }
749 AnimatorSet.Builder b = anim.play(ObjectAnimator.ofFloat(mTopVisibilityView,
750 "translationY", endingY));
Dianne Hackborndf7221c2013-02-26 14:53:55 -0800751 if (mContentAnimations && mContentView != null) {
Adam Powell50efbed2011-02-08 16:20:15 -0800752 b.with(ObjectAnimator.ofFloat(mContentView, "translationY",
Chet Haasee8118e12012-05-30 14:19:02 -0700753 0, endingY));
Adam Powell50efbed2011-02-08 16:20:15 -0800754 }
Adam Powell1ab418a2011-06-09 20:49:49 -0700755 if (mSplitView != null && mSplitView.getVisibility() == View.VISIBLE) {
Adam Powell640a66e2011-04-29 10:18:53 -0700756 mSplitView.setAlpha(1);
Dianne Hackborn8eedb8b2012-04-16 19:31:58 -0700757 b.with(ObjectAnimator.ofFloat(mSplitView, "translationY",
758 mSplitView.getHeight()));
Adam Powell640a66e2011-04-29 10:18:53 -0700759 }
Dianne Hackborn8eedb8b2012-04-16 19:31:58 -0700760 anim.setInterpolator(AnimationUtils.loadInterpolator(mContext,
Chet Haasee8118e12012-05-30 14:19:02 -0700761 com.android.internal.R.interpolator.accelerate_cubic));
762 anim.setDuration(250);
Adam Powell50efbed2011-02-08 16:20:15 -0800763 anim.addListener(mHideListener);
Adam Powell07e1f982011-03-24 11:11:15 -0700764 mCurrentShowAnim = anim;
Adam Powell50efbed2011-02-08 16:20:15 -0800765 anim.start();
766 } else {
767 mHideListener.onAnimationEnd(null);
Adam Powelle6ec7322010-12-07 15:29:26 -0800768 }
Adam Powell6b336f82010-08-10 20:13:01 -0700769 }
770
771 public boolean isShowing() {
Dianne Hackborn139e5aa2012-05-05 20:36:38 -0700772 return mNowShowing;
773 }
774
775 public boolean isSystemShowing() {
776 return !mHiddenBySystem;
Adam Powelld8b3f2e2010-12-02 13:37:03 -0800777 }
778
Adam Powell640a66e2011-04-29 10:18:53 -0700779 void animateToMode(boolean toActionMode) {
Adam Powell060e3ca2011-07-19 20:39:16 -0700780 if (toActionMode) {
Dianne Hackborn139e5aa2012-05-05 20:36:38 -0700781 showForActionMode();
782 } else {
783 hideForActionMode();
Adam Powell07e1f982011-03-24 11:11:15 -0700784 }
Adam Powelld8b3f2e2010-12-02 13:37:03 -0800785
Adam Powell640a66e2011-04-29 10:18:53 -0700786 mActionView.animateToVisibility(toActionMode ? View.GONE : View.VISIBLE);
787 mContextView.animateToVisibility(toActionMode ? View.VISIBLE : View.GONE);
Adam Powellf6ce6a92011-06-29 10:25:01 -0700788 if (mTabScrollView != null && !mActionView.hasEmbeddedTabs() && mActionView.isCollapsed()) {
789 mTabScrollView.animateToVisibility(toActionMode ? View.GONE : View.VISIBLE);
790 }
Adam Powell6b336f82010-08-10 20:13:01 -0700791 }
792
Adam Powell88ab6972011-07-28 11:25:01 -0700793 public Context getThemedContext() {
794 if (mThemedContext == null) {
795 TypedValue outValue = new TypedValue();
796 Resources.Theme currentTheme = mContext.getTheme();
797 currentTheme.resolveAttribute(com.android.internal.R.attr.actionBarWidgetTheme,
798 outValue, true);
799 final int targetThemeRes = outValue.resourceId;
800
801 if (targetThemeRes != 0 && mContext.getThemeResId() != targetThemeRes) {
802 mThemedContext = new ContextThemeWrapper(mContext, targetThemeRes);
803 } else {
804 mThemedContext = mContext;
805 }
806 }
807 return mThemedContext;
808 }
809
Adam Powell27cba382013-01-22 18:55:20 -0800810 @Override
811 public boolean isTitleTruncated() {
812 return mActionView != null && mActionView.isTitleTruncated();
813 }
814
Adam Powell89e06452010-06-23 20:24:52 -0700815 /**
816 * @hide
817 */
Adam Powell5d279772010-07-27 16:34:07 -0700818 public class ActionModeImpl extends ActionMode implements MenuBuilder.Callback {
Adam Powell6e346362010-07-23 10:18:23 -0700819 private ActionMode.Callback mCallback;
Adam Powell2c9c9fe2010-07-16 10:17:57 -0700820 private MenuBuilder mMenu;
Adam Powell29ed7572010-07-14 16:24:56 -0700821 private WeakReference<View> mCustomView;
Adam Powell89e06452010-06-23 20:24:52 -0700822
Adam Powell5d279772010-07-27 16:34:07 -0700823 public ActionModeImpl(ActionMode.Callback callback) {
Adam Powell89e06452010-06-23 20:24:52 -0700824 mCallback = callback;
Adam Powellf2423682011-08-11 14:29:45 -0700825 mMenu = new MenuBuilder(getThemedContext())
Adam Powell4d9861e2010-08-17 11:14:40 -0700826 .setDefaultShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM);
Adam Powell2c9c9fe2010-07-16 10:17:57 -0700827 mMenu.setCallback(this);
Adam Powell89e06452010-06-23 20:24:52 -0700828 }
Adam Powell9168f0b2010-08-02 15:46:24 -0700829
830 @Override
831 public MenuInflater getMenuInflater() {
Adam Powellf2423682011-08-11 14:29:45 -0700832 return new MenuInflater(getThemedContext());
Adam Powell9168f0b2010-08-02 15:46:24 -0700833 }
834
Adam Powell89e06452010-06-23 20:24:52 -0700835 @Override
836 public Menu getMenu() {
837 return mMenu;
838 }
839
840 @Override
841 public void finish() {
Adam Powell5d279772010-07-27 16:34:07 -0700842 if (mActionMode != this) {
843 // Not the active action mode - no-op
Adam Powell93b6bc32010-07-22 11:36:35 -0700844 return;
845 }
846
Dianne Hackborn139e5aa2012-05-05 20:36:38 -0700847 // If this change in state is going to cause the action bar
848 // to be hidden, defer the onDestroy callback until the animation
849 // is finished and associated relayout is about to happen. This lets
850 // apps better anticipate visibility and layout behavior.
851 if (!checkShowingFlags(mHiddenByApp, mHiddenBySystem, false)) {
852 // With the current state but the action bar hidden, our
853 // overall showing state is going to be false.
Adam Powell060e3ca2011-07-19 20:39:16 -0700854 mDeferredDestroyActionMode = this;
855 mDeferredModeDestroyCallback = mCallback;
856 } else {
857 mCallback.onDestroyActionMode(this);
858 }
Adam Powelld8b3f2e2010-12-02 13:37:03 -0800859 mCallback = null;
Adam Powell640a66e2011-04-29 10:18:53 -0700860 animateToMode(false);
Adam Powell0e94b512010-06-29 17:58:20 -0700861
862 // Clear out the context mode views after the animation finishes
Adam Powell640a66e2011-04-29 10:18:53 -0700863 mContextView.closeMode();
Adam Powell86ed4362011-09-14 16:18:53 -0700864 mActionView.sendAccessibilityEvent(AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED);
Adam Powellf6ce6a92011-06-29 10:25:01 -0700865
Adam Powell5d279772010-07-27 16:34:07 -0700866 mActionMode = null;
Adam Powell89e06452010-06-23 20:24:52 -0700867 }
868
869 @Override
870 public void invalidate() {
Adam Powell5ee36c42011-06-02 12:59:43 -0700871 mMenu.stopDispatchingItemsChanged();
872 try {
873 mCallback.onPrepareActionMode(this, mMenu);
874 } finally {
875 mMenu.startDispatchingItemsChanged();
876 }
877 }
878
879 public boolean dispatchOnCreate() {
880 mMenu.stopDispatchingItemsChanged();
881 try {
882 return mCallback.onCreateActionMode(this, mMenu);
883 } finally {
884 mMenu.startDispatchingItemsChanged();
Adam Powell89e06452010-06-23 20:24:52 -0700885 }
886 }
887
888 @Override
889 public void setCustomView(View view) {
Adam Powell640a66e2011-04-29 10:18:53 -0700890 mContextView.setCustomView(view);
Adam Powell29ed7572010-07-14 16:24:56 -0700891 mCustomView = new WeakReference<View>(view);
Adam Powell89e06452010-06-23 20:24:52 -0700892 }
893
894 @Override
895 public void setSubtitle(CharSequence subtitle) {
Adam Powell640a66e2011-04-29 10:18:53 -0700896 mContextView.setSubtitle(subtitle);
Adam Powell89e06452010-06-23 20:24:52 -0700897 }
898
899 @Override
900 public void setTitle(CharSequence title) {
Adam Powell640a66e2011-04-29 10:18:53 -0700901 mContextView.setTitle(title);
Adam Powell89e06452010-06-23 20:24:52 -0700902 }
Adam Powell29ed7572010-07-14 16:24:56 -0700903
904 @Override
Adam Powellc9ae2a22010-07-28 14:44:21 -0700905 public void setTitle(int resId) {
Adam Powell48e8ac32011-01-14 12:10:24 -0800906 setTitle(mContext.getResources().getString(resId));
Adam Powellc9ae2a22010-07-28 14:44:21 -0700907 }
908
909 @Override
910 public void setSubtitle(int resId) {
Adam Powell48e8ac32011-01-14 12:10:24 -0800911 setSubtitle(mContext.getResources().getString(resId));
Adam Powellc9ae2a22010-07-28 14:44:21 -0700912 }
913
914 @Override
Adam Powell29ed7572010-07-14 16:24:56 -0700915 public CharSequence getTitle() {
Adam Powell640a66e2011-04-29 10:18:53 -0700916 return mContextView.getTitle();
Adam Powell29ed7572010-07-14 16:24:56 -0700917 }
918
919 @Override
920 public CharSequence getSubtitle() {
Adam Powell640a66e2011-04-29 10:18:53 -0700921 return mContextView.getSubtitle();
Adam Powell29ed7572010-07-14 16:24:56 -0700922 }
Adam Powell89e06452010-06-23 20:24:52 -0700923
Adam Powell29ed7572010-07-14 16:24:56 -0700924 @Override
Adam Powellb98a81f2012-02-24 11:09:07 -0800925 public void setTitleOptionalHint(boolean titleOptional) {
Adam Powell785c4472012-05-02 21:25:39 -0700926 super.setTitleOptionalHint(titleOptional);
Adam Powellb98a81f2012-02-24 11:09:07 -0800927 mContextView.setTitleOptional(titleOptional);
928 }
929
930 @Override
931 public boolean isTitleOptional() {
932 return mContextView.isTitleOptional();
933 }
934
935 @Override
Adam Powell29ed7572010-07-14 16:24:56 -0700936 public View getCustomView() {
937 return mCustomView != null ? mCustomView.get() : null;
938 }
939
Adam Powell2c9c9fe2010-07-16 10:17:57 -0700940 public boolean onMenuItemSelected(MenuBuilder menu, MenuItem item) {
Adam Powelld8b3f2e2010-12-02 13:37:03 -0800941 if (mCallback != null) {
942 return mCallback.onActionItemClicked(this, item);
943 } else {
944 return false;
945 }
Adam Powell2c9c9fe2010-07-16 10:17:57 -0700946 }
947
948 public void onCloseMenu(MenuBuilder menu, boolean allMenusAreClosing) {
949 }
950
951 public boolean onSubMenuSelected(SubMenuBuilder subMenu) {
Adam Powelld8b3f2e2010-12-02 13:37:03 -0800952 if (mCallback == null) {
953 return false;
954 }
955
Adam Powell2c9c9fe2010-07-16 10:17:57 -0700956 if (!subMenu.hasVisibleItems()) {
957 return true;
Adam Powell89e06452010-06-23 20:24:52 -0700958 }
Adam Powell2c9c9fe2010-07-16 10:17:57 -0700959
Adam Powellf2423682011-08-11 14:29:45 -0700960 new MenuPopupHelper(getThemedContext(), subMenu).show();
Adam Powell2c9c9fe2010-07-16 10:17:57 -0700961 return true;
962 }
963
964 public void onCloseSubMenu(SubMenuBuilder menu) {
965 }
966
967 public void onMenuModeChange(MenuBuilder menu) {
Adam Powelld8b3f2e2010-12-02 13:37:03 -0800968 if (mCallback == null) {
969 return;
970 }
Adam Powellf6148c52010-08-11 21:10:16 -0700971 invalidate();
Adam Powell640a66e2011-04-29 10:18:53 -0700972 mContextView.showOverflowMenu();
Adam Powell2c9c9fe2010-07-16 10:17:57 -0700973 }
Adam Powell661c9082010-07-02 10:09:44 -0700974 }
975
976 /**
977 * @hide
978 */
979 public class TabImpl extends ActionBar.Tab {
Adam Powell2b6230e2010-09-07 17:55:25 -0700980 private ActionBar.TabListener mCallback;
981 private Object mTag;
Adam Powell661c9082010-07-02 10:09:44 -0700982 private Drawable mIcon;
983 private CharSequence mText;
Adam Powell94e56ef2011-09-06 21:22:22 -0700984 private CharSequence mContentDesc;
Adam Powell0d8ec1d2011-05-03 14:49:13 -0700985 private int mPosition = -1;
Adam Powell2b6230e2010-09-07 17:55:25 -0700986 private View mCustomView;
Adam Powell661c9082010-07-02 10:09:44 -0700987
988 @Override
Adam Powell2b6230e2010-09-07 17:55:25 -0700989 public Object getTag() {
990 return mTag;
991 }
992
993 @Override
Adam Powell9ab97872010-10-26 21:47:29 -0700994 public Tab setTag(Object tag) {
Adam Powell2b6230e2010-09-07 17:55:25 -0700995 mTag = tag;
Adam Powell9ab97872010-10-26 21:47:29 -0700996 return this;
Adam Powell2b6230e2010-09-07 17:55:25 -0700997 }
998
999 public ActionBar.TabListener getCallback() {
1000 return mCallback;
1001 }
1002
1003 @Override
Adam Powell9ab97872010-10-26 21:47:29 -07001004 public Tab setTabListener(ActionBar.TabListener callback) {
Adam Powell2b6230e2010-09-07 17:55:25 -07001005 mCallback = callback;
Adam Powell9ab97872010-10-26 21:47:29 -07001006 return this;
Adam Powell2b6230e2010-09-07 17:55:25 -07001007 }
1008
1009 @Override
1010 public View getCustomView() {
1011 return mCustomView;
1012 }
1013
1014 @Override
Adam Powell9ab97872010-10-26 21:47:29 -07001015 public Tab setCustomView(View view) {
Adam Powell2b6230e2010-09-07 17:55:25 -07001016 mCustomView = view;
Adam Powellf8ac6b72011-05-23 18:14:09 -07001017 if (mPosition >= 0) {
1018 mTabScrollView.updateTab(mPosition);
1019 }
Adam Powell9ab97872010-10-26 21:47:29 -07001020 return this;
Adam Powell661c9082010-07-02 10:09:44 -07001021 }
1022
1023 @Override
Adam Powell32555f32010-11-17 13:49:22 -08001024 public Tab setCustomView(int layoutResId) {
Adam Powellf2423682011-08-11 14:29:45 -07001025 return setCustomView(LayoutInflater.from(getThemedContext())
1026 .inflate(layoutResId, null));
Adam Powell32555f32010-11-17 13:49:22 -08001027 }
1028
1029 @Override
Adam Powell661c9082010-07-02 10:09:44 -07001030 public Drawable getIcon() {
1031 return mIcon;
1032 }
1033
1034 @Override
1035 public int getPosition() {
1036 return mPosition;
1037 }
1038
1039 public void setPosition(int position) {
1040 mPosition = position;
1041 }
1042
1043 @Override
1044 public CharSequence getText() {
1045 return mText;
1046 }
1047
1048 @Override
Adam Powell9ab97872010-10-26 21:47:29 -07001049 public Tab setIcon(Drawable icon) {
Adam Powell661c9082010-07-02 10:09:44 -07001050 mIcon = icon;
Adam Powellf8ac6b72011-05-23 18:14:09 -07001051 if (mPosition >= 0) {
1052 mTabScrollView.updateTab(mPosition);
1053 }
Adam Powell9ab97872010-10-26 21:47:29 -07001054 return this;
Adam Powell661c9082010-07-02 10:09:44 -07001055 }
1056
1057 @Override
Adam Powell32555f32010-11-17 13:49:22 -08001058 public Tab setIcon(int resId) {
1059 return setIcon(mContext.getResources().getDrawable(resId));
1060 }
1061
1062 @Override
Adam Powell9ab97872010-10-26 21:47:29 -07001063 public Tab setText(CharSequence text) {
Adam Powell661c9082010-07-02 10:09:44 -07001064 mText = text;
Adam Powellf8ac6b72011-05-23 18:14:09 -07001065 if (mPosition >= 0) {
1066 mTabScrollView.updateTab(mPosition);
1067 }
Adam Powell9ab97872010-10-26 21:47:29 -07001068 return this;
Adam Powell661c9082010-07-02 10:09:44 -07001069 }
1070
1071 @Override
Adam Powell32555f32010-11-17 13:49:22 -08001072 public Tab setText(int resId) {
1073 return setText(mContext.getResources().getText(resId));
1074 }
1075
1076 @Override
Adam Powell661c9082010-07-02 10:09:44 -07001077 public void select() {
1078 selectTab(this);
Adam Powell89e06452010-06-23 20:24:52 -07001079 }
Adam Powell94e56ef2011-09-06 21:22:22 -07001080
1081 @Override
1082 public Tab setContentDescription(int resId) {
1083 return setContentDescription(mContext.getResources().getText(resId));
1084 }
1085
1086 @Override
1087 public Tab setContentDescription(CharSequence contentDesc) {
1088 mContentDesc = contentDesc;
1089 if (mPosition >= 0) {
1090 mTabScrollView.updateTab(mPosition);
1091 }
1092 return this;
1093 }
1094
1095 @Override
1096 public CharSequence getContentDescription() {
1097 return mContentDesc;
1098 }
Adam Powell89e06452010-06-23 20:24:52 -07001099 }
Adam Powell9ab97872010-10-26 21:47:29 -07001100
1101 @Override
1102 public void setCustomView(View view) {
1103 mActionView.setCustomNavigationView(view);
1104 }
1105
1106 @Override
1107 public void setCustomView(View view, LayoutParams layoutParams) {
1108 view.setLayoutParams(layoutParams);
1109 mActionView.setCustomNavigationView(view);
1110 }
1111
1112 @Override
Adam Powell8515ee82010-11-30 14:09:55 -08001113 public void setListNavigationCallbacks(SpinnerAdapter adapter, OnNavigationListener callback) {
Adam Powell9ab97872010-10-26 21:47:29 -07001114 mActionView.setDropdownAdapter(adapter);
1115 mActionView.setCallback(callback);
1116 }
1117
1118 @Override
1119 public int getSelectedNavigationIndex() {
1120 switch (mActionView.getNavigationMode()) {
1121 case NAVIGATION_MODE_TABS:
Adam Powell04587962010-11-11 22:15:07 -08001122 return mSelectedTab != null ? mSelectedTab.getPosition() : -1;
Adam Powell9ab97872010-10-26 21:47:29 -07001123 case NAVIGATION_MODE_LIST:
1124 return mActionView.getDropdownSelectedPosition();
1125 default:
1126 return -1;
1127 }
1128 }
1129
1130 @Override
1131 public int getNavigationItemCount() {
1132 switch (mActionView.getNavigationMode()) {
1133 case NAVIGATION_MODE_TABS:
1134 return mTabs.size();
1135 case NAVIGATION_MODE_LIST:
1136 SpinnerAdapter adapter = mActionView.getDropdownAdapter();
1137 return adapter != null ? adapter.getCount() : 0;
1138 default:
1139 return 0;
1140 }
1141 }
1142
1143 @Override
Adam Powell0c24a552010-11-03 16:44:11 -07001144 public int getTabCount() {
1145 return mTabs.size();
1146 }
1147
1148 @Override
Adam Powell9ab97872010-10-26 21:47:29 -07001149 public void setNavigationMode(int mode) {
Adam Powell0c24a552010-11-03 16:44:11 -07001150 final int oldMode = mActionView.getNavigationMode();
1151 switch (oldMode) {
1152 case NAVIGATION_MODE_TABS:
1153 mSavedTabPosition = getSelectedNavigationIndex();
1154 selectTab(null);
Adam Powellf5645cb2011-08-10 22:49:02 -07001155 mTabScrollView.setVisibility(View.GONE);
Adam Powell0c24a552010-11-03 16:44:11 -07001156 break;
1157 }
Dianne Hackborn3a3a6cf2012-03-26 10:24:04 -07001158 if (oldMode != mode && !mHasEmbeddedTabs) {
1159 if (mOverlayLayout != null) {
1160 mOverlayLayout.requestFitSystemWindows();
1161 }
1162 }
Adam Powell9ab97872010-10-26 21:47:29 -07001163 mActionView.setNavigationMode(mode);
Adam Powell0c24a552010-11-03 16:44:11 -07001164 switch (mode) {
1165 case NAVIGATION_MODE_TABS:
Adam Powellf8ac6b72011-05-23 18:14:09 -07001166 ensureTabsExist();
Adam Powellf5645cb2011-08-10 22:49:02 -07001167 mTabScrollView.setVisibility(View.VISIBLE);
Adam Powell0c24a552010-11-03 16:44:11 -07001168 if (mSavedTabPosition != INVALID_POSITION) {
1169 setSelectedNavigationItem(mSavedTabPosition);
1170 mSavedTabPosition = INVALID_POSITION;
1171 }
1172 break;
1173 }
Adam Powelld21aa122011-05-27 13:09:52 -07001174 mActionView.setCollapsable(mode == NAVIGATION_MODE_TABS && !mHasEmbeddedTabs);
Adam Powell9ab97872010-10-26 21:47:29 -07001175 }
1176
1177 @Override
1178 public Tab getTabAt(int index) {
1179 return mTabs.get(index);
1180 }
Adam Powell0c24a552010-11-03 16:44:11 -07001181
Adam Powell0c24a552010-11-03 16:44:11 -07001182
Adam Powell1969b872011-03-22 11:52:48 -07001183 @Override
1184 public void setIcon(int resId) {
Adam Powell45c515b2011-04-21 18:50:20 -07001185 mActionView.setIcon(resId);
Adam Powell1969b872011-03-22 11:52:48 -07001186 }
Adam Powell0c24a552010-11-03 16:44:11 -07001187
Adam Powell1969b872011-03-22 11:52:48 -07001188 @Override
1189 public void setIcon(Drawable icon) {
1190 mActionView.setIcon(icon);
1191 }
1192
1193 @Override
1194 public void setLogo(int resId) {
Adam Powell45c515b2011-04-21 18:50:20 -07001195 mActionView.setLogo(resId);
Adam Powell1969b872011-03-22 11:52:48 -07001196 }
1197
1198 @Override
1199 public void setLogo(Drawable logo) {
1200 mActionView.setLogo(logo);
Adam Powell0c24a552010-11-03 16:44:11 -07001201 }
Adam Powelldd8fab22012-03-22 17:47:27 -07001202
1203 public void setDefaultDisplayHomeAsUpEnabled(boolean enable) {
1204 if (!mDisplayHomeAsUpSet) {
1205 setDisplayHomeAsUpEnabled(enable);
1206 }
1207 }
Adam Powell89e06452010-06-23 20:24:52 -07001208}