blob: 0a8049536bc4f9b5a4d90042163dde97fbea0cec [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 Powell9b0dc282013-07-31 13:58:43 -070019import android.animation.ValueAnimator;
20import android.view.ViewParent;
Adam Powellb8139af2012-04-19 13:52:46 -070021import com.android.internal.view.ActionBarPolicy;
Adam Powell2c9c9fe2010-07-16 10:17:57 -070022import com.android.internal.view.menu.MenuBuilder;
Adam Powell2c9c9fe2010-07-16 10:17:57 -070023import com.android.internal.view.menu.MenuPopupHelper;
24import com.android.internal.view.menu.SubMenuBuilder;
Adam Powell01feaee2011-02-10 15:05:05 -080025import com.android.internal.widget.ActionBarContainer;
Adam Powell89e06452010-06-23 20:24:52 -070026import com.android.internal.widget.ActionBarContextView;
Dianne Hackborn3a3a6cf2012-03-26 10:24:04 -070027import com.android.internal.widget.ActionBarOverlayLayout;
Adam Powell89e06452010-06-23 20:24:52 -070028import com.android.internal.widget.ActionBarView;
Adam Powellf8ac6b72011-05-23 18:14:09 -070029import com.android.internal.widget.ScrollingTabContainerView;
Adam Powell89e06452010-06-23 20:24:52 -070030
Adam Powelld8b3f2e2010-12-02 13:37:03 -080031import android.animation.Animator;
Adam Powelld8b3f2e2010-12-02 13:37:03 -080032import android.animation.Animator.AnimatorListener;
Adam Powell07e1f982011-03-24 11:11:15 -070033import android.animation.AnimatorListenerAdapter;
Adam Powelld8b3f2e2010-12-02 13:37:03 -080034import android.animation.AnimatorSet;
Adam Powelle6ec7322010-12-07 15:29:26 -080035import android.animation.ObjectAnimator;
Adam Powell89e06452010-06-23 20:24:52 -070036import android.app.ActionBar;
Adam Powell661c9082010-07-02 10:09:44 -070037import android.app.Activity;
Adam Powelldec9dfd2010-08-09 15:27:54 -070038import android.app.Dialog;
Adam Powell661c9082010-07-02 10:09:44 -070039import android.app.FragmentTransaction;
Adam Powelldec9dfd2010-08-09 15:27:54 -070040import android.content.Context;
Adam Powellf8ac6b72011-05-23 18:14:09 -070041import android.content.res.Configuration;
Adam Powell88ab6972011-07-28 11:25:01 -070042import android.content.res.Resources;
Adam Powell89e06452010-06-23 20:24:52 -070043import android.graphics.drawable.Drawable;
Adam Powell0e94b512010-06-29 17:58:20 -070044import android.os.Handler;
Adam Powell88ab6972011-07-28 11:25:01 -070045import android.util.TypedValue;
Adam Powell6e346362010-07-23 10:18:23 -070046import android.view.ActionMode;
Adam Powell88ab6972011-07-28 11:25:01 -070047import android.view.ContextThemeWrapper;
Adam Powell32555f32010-11-17 13:49:22 -080048import android.view.LayoutInflater;
Adam Powell89e06452010-06-23 20:24:52 -070049import android.view.Menu;
Adam Powell9168f0b2010-08-02 15:46:24 -070050import android.view.MenuInflater;
Adam Powell89e06452010-06-23 20:24:52 -070051import android.view.MenuItem;
52import android.view.View;
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;
Adam Powell89e06452010-06-23 20:24:52 -070078 private ActionBarView mActionView;
Adam Powell640a66e2011-04-29 10:18:53 -070079 private ActionBarContextView mContextView;
80 private ActionBarContainer mSplitView;
Adam Powelle6ec7322010-12-07 15:29:26 -080081 private View mContentView;
Adam Powellf8ac6b72011-05-23 18:14:09 -070082 private ScrollingTabContainerView mTabScrollView;
Adam Powell661c9082010-07-02 10:09:44 -070083
84 private ArrayList<TabImpl> mTabs = new ArrayList<TabImpl>();
85
Adam Powell661c9082010-07-02 10:09:44 -070086 private TabImpl mSelectedTab;
Adam Powell0c24a552010-11-03 16:44:11 -070087 private int mSavedTabPosition = INVALID_POSITION;
Adam Powell89e06452010-06-23 20:24:52 -070088
Adam Powelldd8fab22012-03-22 17:47:27 -070089 private boolean mDisplayHomeAsUpSet;
90
Adam Powell060e3ca2011-07-19 20:39:16 -070091 ActionModeImpl mActionMode;
92 ActionMode mDeferredDestroyActionMode;
93 ActionMode.Callback mDeferredModeDestroyCallback;
Adam Powell89e06452010-06-23 20:24:52 -070094
Adam Powell8515ee82010-11-30 14:09:55 -080095 private boolean mLastMenuVisibility;
96 private ArrayList<OnMenuVisibilityListener> mMenuVisibilityListeners =
97 new ArrayList<OnMenuVisibilityListener>();
98
Adam Powell89e06452010-06-23 20:24:52 -070099 private static final int CONTEXT_DISPLAY_NORMAL = 0;
100 private static final int CONTEXT_DISPLAY_SPLIT = 1;
101
Adam Powell0c24a552010-11-03 16:44:11 -0700102 private static final int INVALID_POSITION = -1;
103
Adam Powell89e06452010-06-23 20:24:52 -0700104 private int mContextDisplayMode;
Adam Powellf8ac6b72011-05-23 18:14:09 -0700105 private boolean mHasEmbeddedTabs;
Adam Powell0e94b512010-06-29 17:58:20 -0700106
107 final Handler mHandler = new Handler();
Adam Powellf8ac6b72011-05-23 18:14:09 -0700108 Runnable mTabSelector;
Adam Powelld8b3f2e2010-12-02 13:37:03 -0800109
Dianne Hackborn3a3a6cf2012-03-26 10:24:04 -0700110 private int mCurWindowVisibility = View.VISIBLE;
111
Dianne Hackborndf7221c2013-02-26 14:53:55 -0800112 private boolean mContentAnimations = true;
Dianne Hackborn139e5aa2012-05-05 20:36:38 -0700113 private boolean mHiddenByApp;
114 private boolean mHiddenBySystem;
115 private boolean mShowingForMode;
116
117 private boolean mNowShowing = true;
118
Adam Powell07e1f982011-03-24 11:11:15 -0700119 private Animator mCurrentShowAnim;
Adam Powell50efbed2011-02-08 16:20:15 -0800120 private boolean mShowHideAnimationEnabled;
Adam Powelld8b3f2e2010-12-02 13:37:03 -0800121
Adam Powell07e1f982011-03-24 11:11:15 -0700122 final AnimatorListener mHideListener = new AnimatorListenerAdapter() {
Adam Powelle6ec7322010-12-07 15:29:26 -0800123 @Override
124 public void onAnimationEnd(Animator animation) {
Dianne Hackborndf7221c2013-02-26 14:53:55 -0800125 if (mContentAnimations && mContentView != null) {
Adam Powelle6ec7322010-12-07 15:29:26 -0800126 mContentView.setTranslationY(0);
Adam Powell9b0dc282013-07-31 13:58:43 -0700127 mContainerView.setTranslationY(0);
Adam Powelle6ec7322010-12-07 15:29:26 -0800128 }
Adam Powell993a63a2011-08-18 16:35:53 -0700129 if (mSplitView != null && mContextDisplayMode == CONTEXT_DISPLAY_SPLIT) {
130 mSplitView.setVisibility(View.GONE);
131 }
Adam Powell9b0dc282013-07-31 13:58:43 -0700132 mContainerView.setVisibility(View.GONE);
Adam Powell01feaee2011-02-10 15:05:05 -0800133 mContainerView.setTransitioning(false);
Adam Powell07e1f982011-03-24 11:11:15 -0700134 mCurrentShowAnim = null;
Adam Powell060e3ca2011-07-19 20:39:16 -0700135 completeDeferredDestroyActionMode();
Dianne Hackborn139e5aa2012-05-05 20:36:38 -0700136 if (mOverlayLayout != null) {
137 mOverlayLayout.requestFitSystemWindows();
138 }
Adam Powelle6ec7322010-12-07 15:29:26 -0800139 }
140 };
141
Adam Powell07e1f982011-03-24 11:11:15 -0700142 final AnimatorListener mShowListener = new AnimatorListenerAdapter() {
Adam Powelle6ec7322010-12-07 15:29:26 -0800143 @Override
144 public void onAnimationEnd(Animator animation) {
Adam Powell07e1f982011-03-24 11:11:15 -0700145 mCurrentShowAnim = null;
Adam Powell9b0dc282013-07-31 13:58:43 -0700146 mContainerView.requestLayout();
147 }
148 };
149
150 final ValueAnimator.AnimatorUpdateListener mUpdateListener =
151 new ValueAnimator.AnimatorUpdateListener() {
152 @Override
153 public void onAnimationUpdate(ValueAnimator animation) {
154 final ViewParent parent = mContainerView.getParent();
155 ((View) parent).invalidate();
Adam Powelle6ec7322010-12-07 15:29:26 -0800156 }
Adam Powelle6ec7322010-12-07 15:29:26 -0800157 };
158
Adam Powell661c9082010-07-02 10:09:44 -0700159 public ActionBarImpl(Activity activity) {
Adam Powell661c9082010-07-02 10:09:44 -0700160 mActivity = activity;
Adam Powelle6ec7322010-12-07 15:29:26 -0800161 Window window = activity.getWindow();
162 View decor = window.getDecorView();
Dianne Hackborndf7221c2013-02-26 14:53:55 -0800163 boolean overlayMode = mActivity.getWindow().hasFeature(Window.FEATURE_ACTION_BAR_OVERLAY);
Adam Powell9b0dc282013-07-31 13:58:43 -0700164 init(decor);
Dianne Hackborndf7221c2013-02-26 14:53:55 -0800165 if (!overlayMode) {
Adam Powelle6ec7322010-12-07 15:29:26 -0800166 mContentView = decor.findViewById(android.R.id.content);
167 }
Adam Powelldec9dfd2010-08-09 15:27:54 -0700168 }
169
170 public ActionBarImpl(Dialog dialog) {
171 mDialog = dialog;
Adam Powell9b0dc282013-07-31 13:58:43 -0700172 init(dialog.getWindow().getDecorView());
Adam Powelldec9dfd2010-08-09 15:27:54 -0700173 }
174
Adam Powell9b0dc282013-07-31 13:58:43 -0700175 private void init(View decor) {
Adam Powelldec9dfd2010-08-09 15:27:54 -0700176 mContext = decor.getContext();
Dianne Hackborn3a3a6cf2012-03-26 10:24:04 -0700177 mOverlayLayout = (ActionBarOverlayLayout) decor.findViewById(
178 com.android.internal.R.id.action_bar_overlay_layout);
179 if (mOverlayLayout != null) {
Adam Powell9b0dc282013-07-31 13:58:43 -0700180 mOverlayLayout.setActionBar(this);
Dianne Hackborn3a3a6cf2012-03-26 10:24:04 -0700181 }
Adam Powell89e06452010-06-23 20:24:52 -0700182 mActionView = (ActionBarView) decor.findViewById(com.android.internal.R.id.action_bar);
Adam Powell640a66e2011-04-29 10:18:53 -0700183 mContextView = (ActionBarContextView) decor.findViewById(
Adam Powell89e06452010-06-23 20:24:52 -0700184 com.android.internal.R.id.action_context_bar);
Adam Powell01feaee2011-02-10 15:05:05 -0800185 mContainerView = (ActionBarContainer) decor.findViewById(
Adam Powelld8b3f2e2010-12-02 13:37:03 -0800186 com.android.internal.R.id.action_bar_container);
Adam Powell640a66e2011-04-29 10:18:53 -0700187 mSplitView = (ActionBarContainer) decor.findViewById(
188 com.android.internal.R.id.split_action_bar);
Steve Block08f194b2010-08-24 18:20:48 +0100189
Adam Powell640a66e2011-04-29 10:18:53 -0700190 if (mActionView == null || mContextView == null || mContainerView == null) {
Adam Powell89e06452010-06-23 20:24:52 -0700191 throw new IllegalStateException(getClass().getSimpleName() + " can only be used " +
192 "with a compatible window decor layout");
193 }
Adam Powell0e94b512010-06-29 17:58:20 -0700194
Adam Powell640a66e2011-04-29 10:18:53 -0700195 mActionView.setContextView(mContextView);
Adam Powell9b4bee02011-04-27 19:24:47 -0700196 mContextDisplayMode = mActionView.isSplitActionBar() ?
197 CONTEXT_DISPLAY_SPLIT : CONTEXT_DISPLAY_NORMAL;
Adam Powelldae78242011-04-25 15:23:41 -0700198
Adam Powelld40423a2012-05-02 14:06:03 -0700199 // This was initially read from the action bar style
200 final int current = mActionView.getDisplayOptions();
201 final boolean homeAsUp = (current & DISPLAY_HOME_AS_UP) != 0;
202 if (homeAsUp) {
203 mDisplayHomeAsUpSet = true;
204 }
205
Adam Powellb8139af2012-04-19 13:52:46 -0700206 ActionBarPolicy abp = ActionBarPolicy.get(mContext);
Adam Powelld40423a2012-05-02 14:06:03 -0700207 setHomeButtonEnabled(abp.enableHomeButtonByDefault() || homeAsUp);
Adam Powellb8139af2012-04-19 13:52:46 -0700208 setHasEmbeddedTabs(abp.hasEmbeddedTabs());
Adam Powellf8ac6b72011-05-23 18:14:09 -0700209 }
210
211 public void onConfigurationChanged(Configuration newConfig) {
Adam Powellb8139af2012-04-19 13:52:46 -0700212 setHasEmbeddedTabs(ActionBarPolicy.get(mContext).hasEmbeddedTabs());
Adam Powellf5645cb2011-08-10 22:49:02 -0700213 }
Adam Powellf8ac6b72011-05-23 18:14:09 -0700214
Adam Powellf5645cb2011-08-10 22:49:02 -0700215 private void setHasEmbeddedTabs(boolean hasEmbeddedTabs) {
216 mHasEmbeddedTabs = hasEmbeddedTabs;
Adam Powellf8ac6b72011-05-23 18:14:09 -0700217 // Switch tab layout configuration if needed
218 if (!mHasEmbeddedTabs) {
219 mActionView.setEmbeddedTabView(null);
220 mContainerView.setTabContainer(mTabScrollView);
221 } else {
222 mContainerView.setTabContainer(null);
Adam Powellf8ac6b72011-05-23 18:14:09 -0700223 mActionView.setEmbeddedTabView(mTabScrollView);
224 }
Adam Powellf5645cb2011-08-10 22:49:02 -0700225 final boolean isInTabMode = getNavigationMode() == NAVIGATION_MODE_TABS;
226 if (mTabScrollView != null) {
Dianne Hackborn3a3a6cf2012-03-26 10:24:04 -0700227 if (isInTabMode) {
228 mTabScrollView.setVisibility(View.VISIBLE);
229 if (mOverlayLayout != null) {
230 mOverlayLayout.requestFitSystemWindows();
231 }
232 } else {
233 mTabScrollView.setVisibility(View.GONE);
234 }
Adam Powellf5645cb2011-08-10 22:49:02 -0700235 }
236 mActionView.setCollapsable(!mHasEmbeddedTabs && isInTabMode);
Adam Powellf8ac6b72011-05-23 18:14:09 -0700237 }
238
Dianne Hackborn3a3a6cf2012-03-26 10:24:04 -0700239 public boolean hasNonEmbeddedTabs() {
240 return !mHasEmbeddedTabs && getNavigationMode() == NAVIGATION_MODE_TABS;
241 }
242
Adam Powellf8ac6b72011-05-23 18:14:09 -0700243 private void ensureTabsExist() {
244 if (mTabScrollView != null) {
245 return;
246 }
247
Adam Powellf5645cb2011-08-10 22:49:02 -0700248 ScrollingTabContainerView tabScroller = new ScrollingTabContainerView(mContext);
Adam Powellf8ac6b72011-05-23 18:14:09 -0700249
250 if (mHasEmbeddedTabs) {
251 tabScroller.setVisibility(View.VISIBLE);
252 mActionView.setEmbeddedTabView(tabScroller);
253 } else {
Dianne Hackborn3a3a6cf2012-03-26 10:24:04 -0700254 if (getNavigationMode() == NAVIGATION_MODE_TABS) {
255 tabScroller.setVisibility(View.VISIBLE);
256 if (mOverlayLayout != null) {
257 mOverlayLayout.requestFitSystemWindows();
258 }
259 } else {
260 tabScroller.setVisibility(View.GONE);
261 }
Adam Powelldae78242011-04-25 15:23:41 -0700262 mContainerView.setTabContainer(tabScroller);
Adam Powelldae78242011-04-25 15:23:41 -0700263 }
Adam Powellf8ac6b72011-05-23 18:14:09 -0700264 mTabScrollView = tabScroller;
Adam Powell89e06452010-06-23 20:24:52 -0700265 }
266
Adam Powell060e3ca2011-07-19 20:39:16 -0700267 void completeDeferredDestroyActionMode() {
268 if (mDeferredModeDestroyCallback != null) {
269 mDeferredModeDestroyCallback.onDestroyActionMode(mDeferredDestroyActionMode);
270 mDeferredDestroyActionMode = null;
271 mDeferredModeDestroyCallback = null;
272 }
273 }
274
Dianne Hackborn3a3a6cf2012-03-26 10:24:04 -0700275 public void setWindowVisibility(int visibility) {
276 mCurWindowVisibility = visibility;
277 }
278
Adam Powell50efbed2011-02-08 16:20:15 -0800279 /**
280 * Enables or disables animation between show/hide states.
281 * If animation is disabled using this method, animations in progress
282 * will be finished.
283 *
284 * @param enabled true to animate, false to not animate.
285 */
286 public void setShowHideAnimationEnabled(boolean enabled) {
287 mShowHideAnimationEnabled = enabled;
Adam Powell07e1f982011-03-24 11:11:15 -0700288 if (!enabled && mCurrentShowAnim != null) {
289 mCurrentShowAnim.end();
Adam Powell50efbed2011-02-08 16:20:15 -0800290 }
291 }
292
Adam Powell8515ee82010-11-30 14:09:55 -0800293 public void addOnMenuVisibilityListener(OnMenuVisibilityListener listener) {
294 mMenuVisibilityListeners.add(listener);
295 }
296
297 public void removeOnMenuVisibilityListener(OnMenuVisibilityListener listener) {
298 mMenuVisibilityListeners.remove(listener);
299 }
300
301 public void dispatchMenuVisibilityChanged(boolean isVisible) {
302 if (isVisible == mLastMenuVisibility) {
303 return;
304 }
305 mLastMenuVisibility = isVisible;
306
307 final int count = mMenuVisibilityListeners.size();
308 for (int i = 0; i < count; i++) {
309 mMenuVisibilityListeners.get(i).onMenuVisibilityChanged(isVisible);
310 }
311 }
312
Adam Powella66c7b02010-07-28 15:28:25 -0700313 @Override
Adam Powell3f476b32011-01-03 19:25:36 -0800314 public void setCustomView(int resId) {
Adam Powellf2423682011-08-11 14:29:45 -0700315 setCustomView(LayoutInflater.from(getThemedContext()).inflate(resId, mActionView, false));
Adam Powell3f476b32011-01-03 19:25:36 -0800316 }
317
318 @Override
319 public void setDisplayUseLogoEnabled(boolean useLogo) {
320 setDisplayOptions(useLogo ? DISPLAY_USE_LOGO : 0, DISPLAY_USE_LOGO);
321 }
322
323 @Override
324 public void setDisplayShowHomeEnabled(boolean showHome) {
325 setDisplayOptions(showHome ? DISPLAY_SHOW_HOME : 0, DISPLAY_SHOW_HOME);
326 }
327
328 @Override
329 public void setDisplayHomeAsUpEnabled(boolean showHomeAsUp) {
330 setDisplayOptions(showHomeAsUp ? DISPLAY_HOME_AS_UP : 0, DISPLAY_HOME_AS_UP);
331 }
332
333 @Override
334 public void setDisplayShowTitleEnabled(boolean showTitle) {
335 setDisplayOptions(showTitle ? DISPLAY_SHOW_TITLE : 0, DISPLAY_SHOW_TITLE);
336 }
337
338 @Override
339 public void setDisplayShowCustomEnabled(boolean showCustom) {
340 setDisplayOptions(showCustom ? DISPLAY_SHOW_CUSTOM : 0, DISPLAY_SHOW_CUSTOM);
341 }
342
343 @Override
Adam Powellc29f4e52011-07-13 20:40:52 -0700344 public void setHomeButtonEnabled(boolean enable) {
345 mActionView.setHomeButtonEnabled(enable);
Adam Powelldae78242011-04-25 15:23:41 -0700346 }
347
348 @Override
Adam Powella66c7b02010-07-28 15:28:25 -0700349 public void setTitle(int resId) {
Adam Powelldec9dfd2010-08-09 15:27:54 -0700350 setTitle(mContext.getString(resId));
Adam Powella66c7b02010-07-28 15:28:25 -0700351 }
352
353 @Override
354 public void setSubtitle(int resId) {
Adam Powelldec9dfd2010-08-09 15:27:54 -0700355 setSubtitle(mContext.getString(resId));
Adam Powella66c7b02010-07-28 15:28:25 -0700356 }
357
Adam Powell17809772010-07-21 13:25:11 -0700358 public void setSelectedNavigationItem(int position) {
359 switch (mActionView.getNavigationMode()) {
360 case NAVIGATION_MODE_TABS:
361 selectTab(mTabs.get(position));
362 break;
Adam Powell9ab97872010-10-26 21:47:29 -0700363 case NAVIGATION_MODE_LIST:
Adam Powell17809772010-07-21 13:25:11 -0700364 mActionView.setDropdownSelectedPosition(position);
365 break;
366 default:
367 throw new IllegalStateException(
Adam Powell9ab97872010-10-26 21:47:29 -0700368 "setSelectedNavigationIndex not valid for current navigation mode");
Adam Powell17809772010-07-21 13:25:11 -0700369 }
370 }
371
Adam Powell9ab97872010-10-26 21:47:29 -0700372 public void removeAllTabs() {
373 cleanupTabs();
Adam Powell17809772010-07-21 13:25:11 -0700374 }
375
Adam Powell661c9082010-07-02 10:09:44 -0700376 private void cleanupTabs() {
377 if (mSelectedTab != null) {
378 selectTab(null);
379 }
Adam Powell2b6230e2010-09-07 17:55:25 -0700380 mTabs.clear();
Adam Powelld21aa122011-05-27 13:09:52 -0700381 if (mTabScrollView != null) {
382 mTabScrollView.removeAllTabs();
383 }
Adam Powell0c24a552010-11-03 16:44:11 -0700384 mSavedTabPosition = INVALID_POSITION;
Adam Powell661c9082010-07-02 10:09:44 -0700385 }
386
Adam Powell0e94b512010-06-29 17:58:20 -0700387 public void setTitle(CharSequence title) {
388 mActionView.setTitle(title);
389 }
390
391 public void setSubtitle(CharSequence subtitle) {
392 mActionView.setSubtitle(subtitle);
393 }
394
Adam Powell89e06452010-06-23 20:24:52 -0700395 public void setDisplayOptions(int options) {
Adam Powelldd8fab22012-03-22 17:47:27 -0700396 if ((options & DISPLAY_HOME_AS_UP) != 0) {
397 mDisplayHomeAsUpSet = true;
398 }
Adam Powell89e06452010-06-23 20:24:52 -0700399 mActionView.setDisplayOptions(options);
400 }
Adam Powell0e94b512010-06-29 17:58:20 -0700401
Adam Powell89e06452010-06-23 20:24:52 -0700402 public void setDisplayOptions(int options, int mask) {
403 final int current = mActionView.getDisplayOptions();
Adam Powelldd8fab22012-03-22 17:47:27 -0700404 if ((mask & DISPLAY_HOME_AS_UP) != 0) {
405 mDisplayHomeAsUpSet = true;
406 }
Adam Powell89e06452010-06-23 20:24:52 -0700407 mActionView.setDisplayOptions((options & mask) | (current & ~mask));
408 }
409
410 public void setBackgroundDrawable(Drawable d) {
Adam Powellf88b9152011-09-07 14:54:32 -0700411 mContainerView.setPrimaryBackground(d);
412 }
413
414 public void setStackedBackgroundDrawable(Drawable d) {
415 mContainerView.setStackedBackground(d);
416 }
417
418 public void setSplitBackgroundDrawable(Drawable d) {
419 if (mSplitView != null) {
420 mSplitView.setSplitBackground(d);
421 }
Adam Powell89e06452010-06-23 20:24:52 -0700422 }
423
Adam Powellef704442010-11-16 14:48:22 -0800424 public View getCustomView() {
Adam Powell89e06452010-06-23 20:24:52 -0700425 return mActionView.getCustomNavigationView();
426 }
427
428 public CharSequence getTitle() {
429 return mActionView.getTitle();
430 }
431
432 public CharSequence getSubtitle() {
433 return mActionView.getSubtitle();
434 }
435
436 public int getNavigationMode() {
437 return mActionView.getNavigationMode();
438 }
439
440 public int getDisplayOptions() {
441 return mActionView.getDisplayOptions();
442 }
443
Adam Powell5d279772010-07-27 16:34:07 -0700444 public ActionMode startActionMode(ActionMode.Callback callback) {
445 if (mActionMode != null) {
446 mActionMode.finish();
Adam Powell6e346362010-07-23 10:18:23 -0700447 }
Adam Powell3461b322010-07-14 11:34:43 -0700448
Adam Powell640a66e2011-04-29 10:18:53 -0700449 mContextView.killMode();
Adam Powell5ee36c42011-06-02 12:59:43 -0700450 ActionModeImpl mode = new ActionModeImpl(callback);
451 if (mode.dispatchOnCreate()) {
Adam Powell2c9c9fe2010-07-16 10:17:57 -0700452 mode.invalidate();
Adam Powell640a66e2011-04-29 10:18:53 -0700453 mContextView.initForMode(mode);
454 animateToMode(true);
Adam Powell1ab418a2011-06-09 20:49:49 -0700455 if (mSplitView != null && mContextDisplayMode == CONTEXT_DISPLAY_SPLIT) {
Adam Powell89e06452010-06-23 20:24:52 -0700456 // TODO animate this
Dianne Hackborn3a3a6cf2012-03-26 10:24:04 -0700457 if (mSplitView.getVisibility() != View.VISIBLE) {
458 mSplitView.setVisibility(View.VISIBLE);
459 if (mOverlayLayout != null) {
460 mOverlayLayout.requestFitSystemWindows();
461 }
462 }
Adam Powell89e06452010-06-23 20:24:52 -0700463 }
Adam Powell86ed4362011-09-14 16:18:53 -0700464 mContextView.sendAccessibilityEvent(AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED);
Adam Powell5d279772010-07-27 16:34:07 -0700465 mActionMode = mode;
Adam Powellac695c62010-07-20 18:19:27 -0700466 return mode;
Adam Powell89e06452010-06-23 20:24:52 -0700467 }
Adam Powellac695c62010-07-20 18:19:27 -0700468 return null;
Adam Powell89e06452010-06-23 20:24:52 -0700469 }
470
Adam Powell661c9082010-07-02 10:09:44 -0700471 private void configureTab(Tab tab, int position) {
472 final TabImpl tabi = (TabImpl) tab;
Adam Powell2b6230e2010-09-07 17:55:25 -0700473 final ActionBar.TabListener callback = tabi.getCallback();
474
475 if (callback == null) {
476 throw new IllegalStateException("Action Bar Tab must have a Callback");
477 }
Adam Powell661c9082010-07-02 10:09:44 -0700478
479 tabi.setPosition(position);
480 mTabs.add(position, tabi);
481
Adam Powell81b89442010-11-02 17:58:56 -0700482 final int count = mTabs.size();
483 for (int i = position + 1; i < count; i++) {
484 mTabs.get(i).setPosition(i);
Adam Powell661c9082010-07-02 10:09:44 -0700485 }
Adam Powell661c9082010-07-02 10:09:44 -0700486 }
487
488 @Override
489 public void addTab(Tab tab) {
Adam Powell81b89442010-11-02 17:58:56 -0700490 addTab(tab, mTabs.isEmpty());
Adam Powell661c9082010-07-02 10:09:44 -0700491 }
492
493 @Override
Adam Powell2b6230e2010-09-07 17:55:25 -0700494 public void addTab(Tab tab, int position) {
Adam Powell81b89442010-11-02 17:58:56 -0700495 addTab(tab, position, mTabs.isEmpty());
496 }
497
498 @Override
499 public void addTab(Tab tab, boolean setSelected) {
Adam Powellf8ac6b72011-05-23 18:14:09 -0700500 ensureTabsExist();
501 mTabScrollView.addTab(tab, setSelected);
Adam Powell81b89442010-11-02 17:58:56 -0700502 configureTab(tab, mTabs.size());
503 if (setSelected) {
504 selectTab(tab);
505 }
506 }
507
508 @Override
509 public void addTab(Tab tab, int position, boolean setSelected) {
Adam Powellf8ac6b72011-05-23 18:14:09 -0700510 ensureTabsExist();
511 mTabScrollView.addTab(tab, position, setSelected);
Adam Powell661c9082010-07-02 10:09:44 -0700512 configureTab(tab, position);
Adam Powell81b89442010-11-02 17:58:56 -0700513 if (setSelected) {
514 selectTab(tab);
515 }
Adam Powell661c9082010-07-02 10:09:44 -0700516 }
517
518 @Override
519 public Tab newTab() {
520 return new TabImpl();
521 }
522
523 @Override
524 public void removeTab(Tab tab) {
525 removeTabAt(tab.getPosition());
526 }
527
528 @Override
529 public void removeTabAt(int position) {
Adam Powellf8ac6b72011-05-23 18:14:09 -0700530 if (mTabScrollView == null) {
531 // No tabs around to remove
532 return;
533 }
534
Adam Powell0c24a552010-11-03 16:44:11 -0700535 int selectedTabPosition = mSelectedTab != null
536 ? mSelectedTab.getPosition() : mSavedTabPosition;
Adam Powellf8ac6b72011-05-23 18:14:09 -0700537 mTabScrollView.removeTabAt(position);
Adam Powell0d8ec1d2011-05-03 14:49:13 -0700538 TabImpl removedTab = mTabs.remove(position);
539 if (removedTab != null) {
540 removedTab.setPosition(-1);
541 }
Adam Powell661c9082010-07-02 10:09:44 -0700542
543 final int newTabCount = mTabs.size();
544 for (int i = position; i < newTabCount; i++) {
545 mTabs.get(i).setPosition(i);
546 }
547
Adam Powell0c24a552010-11-03 16:44:11 -0700548 if (selectedTabPosition == position) {
549 selectTab(mTabs.isEmpty() ? null : mTabs.get(Math.max(0, position - 1)));
550 }
Adam Powell661c9082010-07-02 10:09:44 -0700551 }
552
553 @Override
Adam Powell661c9082010-07-02 10:09:44 -0700554 public void selectTab(Tab tab) {
Adam Powell0c24a552010-11-03 16:44:11 -0700555 if (getNavigationMode() != NAVIGATION_MODE_TABS) {
556 mSavedTabPosition = tab != null ? tab.getPosition() : INVALID_POSITION;
557 return;
558 }
559
Dianne Hackborn48e7b452011-01-17 12:28:35 -0800560 final FragmentTransaction trans = mActivity.getFragmentManager().beginTransaction()
Adam Powell0c24a552010-11-03 16:44:11 -0700561 .disallowAddToBackStack();
Adam Powell7f9b9052010-10-19 16:56:07 -0700562
563 if (mSelectedTab == tab) {
564 if (mSelectedTab != null) {
565 mSelectedTab.getCallback().onTabReselected(mSelectedTab, trans);
Adam Powellf8ac6b72011-05-23 18:14:09 -0700566 mTabScrollView.animateToTab(tab.getPosition());
Adam Powell7f9b9052010-10-19 16:56:07 -0700567 }
568 } else {
Adam Powellf8ac6b72011-05-23 18:14:09 -0700569 mTabScrollView.setTabSelected(tab != null ? tab.getPosition() : Tab.INVALID_POSITION);
Adam Powell7f9b9052010-10-19 16:56:07 -0700570 if (mSelectedTab != null) {
571 mSelectedTab.getCallback().onTabUnselected(mSelectedTab, trans);
572 }
573 mSelectedTab = (TabImpl) tab;
574 if (mSelectedTab != null) {
575 mSelectedTab.getCallback().onTabSelected(mSelectedTab, trans);
576 }
Adam Powell2b6230e2010-09-07 17:55:25 -0700577 }
578
579 if (!trans.isEmpty()) {
580 trans.commit();
581 }
582 }
583
584 @Override
585 public Tab getSelectedTab() {
586 return mSelectedTab;
Adam Powell661c9082010-07-02 10:09:44 -0700587 }
588
Adam Powell6b336f82010-08-10 20:13:01 -0700589 @Override
590 public int getHeight() {
Adam Powell58c5dc12011-07-14 21:08:10 -0700591 return mContainerView.getHeight();
Adam Powell6b336f82010-08-10 20:13:01 -0700592 }
593
Dianne Hackborndf7221c2013-02-26 14:53:55 -0800594 public void enableContentAnimations(boolean enabled) {
595 mContentAnimations = enabled;
596 }
597
Adam Powell6b336f82010-08-10 20:13:01 -0700598 @Override
599 public void show() {
Dianne Hackborn139e5aa2012-05-05 20:36:38 -0700600 if (mHiddenByApp) {
601 mHiddenByApp = false;
602 updateVisibility(false);
603 }
Adam Powell07e1f982011-03-24 11:11:15 -0700604 }
605
Dianne Hackborn139e5aa2012-05-05 20:36:38 -0700606 private void showForActionMode() {
607 if (!mShowingForMode) {
608 mShowingForMode = true;
609 if (mOverlayLayout != null) {
610 mOverlayLayout.setShowingForActionMode(true);
611 }
612 updateVisibility(false);
613 }
614 }
615
616 public void showForSystem() {
617 if (mHiddenBySystem) {
618 mHiddenBySystem = false;
619 updateVisibility(true);
620 }
621 }
622
623 @Override
624 public void hide() {
625 if (!mHiddenByApp) {
626 mHiddenByApp = true;
627 updateVisibility(false);
628 }
629 }
630
631 private void hideForActionMode() {
632 if (mShowingForMode) {
633 mShowingForMode = false;
634 if (mOverlayLayout != null) {
635 mOverlayLayout.setShowingForActionMode(false);
636 }
637 updateVisibility(false);
638 }
639 }
640
641 public void hideForSystem() {
642 if (!mHiddenBySystem) {
643 mHiddenBySystem = true;
644 updateVisibility(true);
645 }
646 }
647
648 private static boolean checkShowingFlags(boolean hiddenByApp, boolean hiddenBySystem,
649 boolean showingForMode) {
650 if (showingForMode) {
651 return true;
652 } else if (hiddenByApp || hiddenBySystem) {
653 return false;
654 } else {
655 return true;
656 }
657 }
658
659 private void updateVisibility(boolean fromSystem) {
660 // Based on the current state, should we be hidden or shown?
661 final boolean shown = checkShowingFlags(mHiddenByApp, mHiddenBySystem,
662 mShowingForMode);
663
664 if (shown) {
665 if (!mNowShowing) {
666 mNowShowing = true;
667 doShow(fromSystem);
668 }
669 } else {
670 if (mNowShowing) {
671 mNowShowing = false;
672 doHide(fromSystem);
673 }
674 }
675 }
676
677 public void doShow(boolean fromSystem) {
Adam Powell07e1f982011-03-24 11:11:15 -0700678 if (mCurrentShowAnim != null) {
679 mCurrentShowAnim.end();
Adam Powell45f1e082010-12-10 14:20:13 -0800680 }
Adam Powell9b0dc282013-07-31 13:58:43 -0700681 mContainerView.setVisibility(View.VISIBLE);
Adam Powell50efbed2011-02-08 16:20:15 -0800682
Dianne Hackborn3a3a6cf2012-03-26 10:24:04 -0700683 if (mCurWindowVisibility == View.VISIBLE && (mShowHideAnimationEnabled
Dianne Hackborn139e5aa2012-05-05 20:36:38 -0700684 || fromSystem)) {
Adam Powell9b0dc282013-07-31 13:58:43 -0700685 mContainerView.setTranslationY(0); // because we're about to ask its window loc
686 float startingY = -mContainerView.getHeight();
Chet Haasee8118e12012-05-30 14:19:02 -0700687 if (fromSystem) {
688 int topLeft[] = {0, 0};
Adam Powell9b0dc282013-07-31 13:58:43 -0700689 mContainerView.getLocationInWindow(topLeft);
Chet Haasee8118e12012-05-30 14:19:02 -0700690 startingY -= topLeft[1];
691 }
Adam Powell9b0dc282013-07-31 13:58:43 -0700692 mContainerView.setTranslationY(startingY);
Adam Powell50efbed2011-02-08 16:20:15 -0800693 AnimatorSet anim = new AnimatorSet();
Adam Powell9b0dc282013-07-31 13:58:43 -0700694 ObjectAnimator a = ObjectAnimator.ofFloat(mContainerView, View.TRANSLATION_Y, 0);
695 a.addUpdateListener(mUpdateListener);
696 AnimatorSet.Builder b = anim.play(a);
Dianne Hackborndf7221c2013-02-26 14:53:55 -0800697 if (mContentAnimations && mContentView != null) {
Adam Powell9b0dc282013-07-31 13:58:43 -0700698 b.with(ObjectAnimator.ofFloat(mContentView, View.TRANSLATION_Y,
Chet Haasee8118e12012-05-30 14:19:02 -0700699 startingY, 0));
Adam Powell50efbed2011-02-08 16:20:15 -0800700 }
Adam Powell1ab418a2011-06-09 20:49:49 -0700701 if (mSplitView != null && mContextDisplayMode == CONTEXT_DISPLAY_SPLIT) {
Dianne Hackborn8eedb8b2012-04-16 19:31:58 -0700702 mSplitView.setTranslationY(mSplitView.getHeight());
Adam Powell993a63a2011-08-18 16:35:53 -0700703 mSplitView.setVisibility(View.VISIBLE);
Adam Powell9b0dc282013-07-31 13:58:43 -0700704 b.with(ObjectAnimator.ofFloat(mSplitView, View.TRANSLATION_Y, 0));
Adam Powell640a66e2011-04-29 10:18:53 -0700705 }
Dianne Hackborn8eedb8b2012-04-16 19:31:58 -0700706 anim.setInterpolator(AnimationUtils.loadInterpolator(mContext,
Chet Haasee8118e12012-05-30 14:19:02 -0700707 com.android.internal.R.interpolator.decelerate_cubic));
708 anim.setDuration(250);
Dianne Hackborn139e5aa2012-05-05 20:36:38 -0700709 // If this is being shown from the system, add a small delay.
710 // This is because we will also be animating in the status bar,
711 // and these two elements can't be done in lock-step. So we give
712 // a little time for the status bar to start its animation before
713 // the action bar animates. (This corresponds to the corresponding
714 // case when hiding, where the status bar has a small delay before
715 // starting.)
Adam Powell50efbed2011-02-08 16:20:15 -0800716 anim.addListener(mShowListener);
Adam Powell07e1f982011-03-24 11:11:15 -0700717 mCurrentShowAnim = anim;
Adam Powell50efbed2011-02-08 16:20:15 -0800718 anim.start();
719 } else {
Adam Powell9b0dc282013-07-31 13:58:43 -0700720 mContainerView.setAlpha(1);
721 mContainerView.setTranslationY(0);
Dianne Hackborndf7221c2013-02-26 14:53:55 -0800722 if (mContentAnimations && mContentView != null) {
Dianne Hackborn80d55062012-05-22 18:03:20 -0700723 mContentView.setTranslationY(0);
724 }
725 if (mSplitView != null && mContextDisplayMode == CONTEXT_DISPLAY_SPLIT) {
726 mSplitView.setAlpha(1);
727 mSplitView.setTranslationY(0);
728 mSplitView.setVisibility(View.VISIBLE);
729 }
Adam Powell50efbed2011-02-08 16:20:15 -0800730 mShowListener.onAnimationEnd(null);
Adam Powelle6ec7322010-12-07 15:29:26 -0800731 }
Dianne Hackborn139e5aa2012-05-05 20:36:38 -0700732 if (mOverlayLayout != null) {
733 mOverlayLayout.requestFitSystemWindows();
734 }
Adam Powell6b336f82010-08-10 20:13:01 -0700735 }
736
Dianne Hackborn139e5aa2012-05-05 20:36:38 -0700737 public void doHide(boolean fromSystem) {
Adam Powell07e1f982011-03-24 11:11:15 -0700738 if (mCurrentShowAnim != null) {
739 mCurrentShowAnim.end();
Adam Powelle6ec7322010-12-07 15:29:26 -0800740 }
Adam Powell50efbed2011-02-08 16:20:15 -0800741
Dianne Hackborn3a3a6cf2012-03-26 10:24:04 -0700742 if (mCurWindowVisibility == View.VISIBLE && (mShowHideAnimationEnabled
Dianne Hackborn139e5aa2012-05-05 20:36:38 -0700743 || fromSystem)) {
Adam Powell9b0dc282013-07-31 13:58:43 -0700744 mContainerView.setAlpha(1);
Adam Powell01feaee2011-02-10 15:05:05 -0800745 mContainerView.setTransitioning(true);
Adam Powell50efbed2011-02-08 16:20:15 -0800746 AnimatorSet anim = new AnimatorSet();
Adam Powell9b0dc282013-07-31 13:58:43 -0700747 float endingY = -mContainerView.getHeight();
Chet Haasee8118e12012-05-30 14:19:02 -0700748 if (fromSystem) {
749 int topLeft[] = {0, 0};
Adam Powell9b0dc282013-07-31 13:58:43 -0700750 mContainerView.getLocationInWindow(topLeft);
Chet Haasee8118e12012-05-30 14:19:02 -0700751 endingY -= topLeft[1];
752 }
Adam Powell9b0dc282013-07-31 13:58:43 -0700753 ObjectAnimator a = ObjectAnimator.ofFloat(mContainerView, View.TRANSLATION_Y, endingY);
754 a.addUpdateListener(mUpdateListener);
755 AnimatorSet.Builder b = anim.play(a);
Dianne Hackborndf7221c2013-02-26 14:53:55 -0800756 if (mContentAnimations && mContentView != null) {
Adam Powell9b0dc282013-07-31 13:58:43 -0700757 b.with(ObjectAnimator.ofFloat(mContentView, View.TRANSLATION_Y,
Chet Haasee8118e12012-05-30 14:19:02 -0700758 0, endingY));
Adam Powell50efbed2011-02-08 16:20:15 -0800759 }
Adam Powell1ab418a2011-06-09 20:49:49 -0700760 if (mSplitView != null && mSplitView.getVisibility() == View.VISIBLE) {
Adam Powell640a66e2011-04-29 10:18:53 -0700761 mSplitView.setAlpha(1);
Adam Powell9b0dc282013-07-31 13:58:43 -0700762 b.with(ObjectAnimator.ofFloat(mSplitView, View.TRANSLATION_Y,
Dianne Hackborn8eedb8b2012-04-16 19:31:58 -0700763 mSplitView.getHeight()));
Adam Powell640a66e2011-04-29 10:18:53 -0700764 }
Dianne Hackborn8eedb8b2012-04-16 19:31:58 -0700765 anim.setInterpolator(AnimationUtils.loadInterpolator(mContext,
Chet Haasee8118e12012-05-30 14:19:02 -0700766 com.android.internal.R.interpolator.accelerate_cubic));
767 anim.setDuration(250);
Adam Powell50efbed2011-02-08 16:20:15 -0800768 anim.addListener(mHideListener);
Adam Powell07e1f982011-03-24 11:11:15 -0700769 mCurrentShowAnim = anim;
Adam Powell50efbed2011-02-08 16:20:15 -0800770 anim.start();
771 } else {
772 mHideListener.onAnimationEnd(null);
Adam Powelle6ec7322010-12-07 15:29:26 -0800773 }
Adam Powell6b336f82010-08-10 20:13:01 -0700774 }
775
776 public boolean isShowing() {
Dianne Hackborn139e5aa2012-05-05 20:36:38 -0700777 return mNowShowing;
778 }
779
780 public boolean isSystemShowing() {
781 return !mHiddenBySystem;
Adam Powelld8b3f2e2010-12-02 13:37:03 -0800782 }
783
Adam Powell640a66e2011-04-29 10:18:53 -0700784 void animateToMode(boolean toActionMode) {
Adam Powell060e3ca2011-07-19 20:39:16 -0700785 if (toActionMode) {
Dianne Hackborn139e5aa2012-05-05 20:36:38 -0700786 showForActionMode();
787 } else {
788 hideForActionMode();
Adam Powell07e1f982011-03-24 11:11:15 -0700789 }
Adam Powelld8b3f2e2010-12-02 13:37:03 -0800790
Adam Powell640a66e2011-04-29 10:18:53 -0700791 mActionView.animateToVisibility(toActionMode ? View.GONE : View.VISIBLE);
792 mContextView.animateToVisibility(toActionMode ? View.VISIBLE : View.GONE);
Adam Powellf6ce6a92011-06-29 10:25:01 -0700793 if (mTabScrollView != null && !mActionView.hasEmbeddedTabs() && mActionView.isCollapsed()) {
794 mTabScrollView.animateToVisibility(toActionMode ? View.GONE : View.VISIBLE);
795 }
Adam Powell6b336f82010-08-10 20:13:01 -0700796 }
797
Adam Powell88ab6972011-07-28 11:25:01 -0700798 public Context getThemedContext() {
799 if (mThemedContext == null) {
800 TypedValue outValue = new TypedValue();
801 Resources.Theme currentTheme = mContext.getTheme();
802 currentTheme.resolveAttribute(com.android.internal.R.attr.actionBarWidgetTheme,
803 outValue, true);
804 final int targetThemeRes = outValue.resourceId;
805
806 if (targetThemeRes != 0 && mContext.getThemeResId() != targetThemeRes) {
807 mThemedContext = new ContextThemeWrapper(mContext, targetThemeRes);
808 } else {
809 mThemedContext = mContext;
810 }
811 }
812 return mThemedContext;
813 }
814
Adam Powell27cba382013-01-22 18:55:20 -0800815 @Override
816 public boolean isTitleTruncated() {
817 return mActionView != null && mActionView.isTitleTruncated();
818 }
819
Adam Powelle0e2f4f2013-04-05 16:27:35 -0700820 @Override
821 public void setHomeAsUpIndicator(Drawable indicator) {
822 mActionView.setHomeAsUpIndicator(indicator);
823 }
824
825 @Override
826 public void setHomeAsUpIndicator(int resId) {
827 mActionView.setHomeAsUpIndicator(resId);
828 }
829
830 @Override
831 public void setHomeActionContentDescription(CharSequence description) {
832 mActionView.setHomeActionContentDescription(description);
833 }
834
835 @Override
836 public void setHomeActionContentDescription(int resId) {
837 mActionView.setHomeActionContentDescription(resId);
838 }
839
Adam Powell89e06452010-06-23 20:24:52 -0700840 /**
841 * @hide
842 */
Adam Powell5d279772010-07-27 16:34:07 -0700843 public class ActionModeImpl extends ActionMode implements MenuBuilder.Callback {
Adam Powell6e346362010-07-23 10:18:23 -0700844 private ActionMode.Callback mCallback;
Adam Powell2c9c9fe2010-07-16 10:17:57 -0700845 private MenuBuilder mMenu;
Adam Powell29ed7572010-07-14 16:24:56 -0700846 private WeakReference<View> mCustomView;
Adam Powell89e06452010-06-23 20:24:52 -0700847
Adam Powell5d279772010-07-27 16:34:07 -0700848 public ActionModeImpl(ActionMode.Callback callback) {
Adam Powell89e06452010-06-23 20:24:52 -0700849 mCallback = callback;
Adam Powellf2423682011-08-11 14:29:45 -0700850 mMenu = new MenuBuilder(getThemedContext())
Adam Powell4d9861e2010-08-17 11:14:40 -0700851 .setDefaultShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM);
Adam Powell2c9c9fe2010-07-16 10:17:57 -0700852 mMenu.setCallback(this);
Adam Powell89e06452010-06-23 20:24:52 -0700853 }
Adam Powell9168f0b2010-08-02 15:46:24 -0700854
855 @Override
856 public MenuInflater getMenuInflater() {
Adam Powellf2423682011-08-11 14:29:45 -0700857 return new MenuInflater(getThemedContext());
Adam Powell9168f0b2010-08-02 15:46:24 -0700858 }
859
Adam Powell89e06452010-06-23 20:24:52 -0700860 @Override
861 public Menu getMenu() {
862 return mMenu;
863 }
864
865 @Override
866 public void finish() {
Adam Powell5d279772010-07-27 16:34:07 -0700867 if (mActionMode != this) {
868 // Not the active action mode - no-op
Adam Powell93b6bc32010-07-22 11:36:35 -0700869 return;
870 }
871
Dianne Hackborn139e5aa2012-05-05 20:36:38 -0700872 // If this change in state is going to cause the action bar
873 // to be hidden, defer the onDestroy callback until the animation
874 // is finished and associated relayout is about to happen. This lets
875 // apps better anticipate visibility and layout behavior.
876 if (!checkShowingFlags(mHiddenByApp, mHiddenBySystem, false)) {
877 // With the current state but the action bar hidden, our
878 // overall showing state is going to be false.
Adam Powell060e3ca2011-07-19 20:39:16 -0700879 mDeferredDestroyActionMode = this;
880 mDeferredModeDestroyCallback = mCallback;
881 } else {
882 mCallback.onDestroyActionMode(this);
883 }
Adam Powelld8b3f2e2010-12-02 13:37:03 -0800884 mCallback = null;
Adam Powell640a66e2011-04-29 10:18:53 -0700885 animateToMode(false);
Adam Powell0e94b512010-06-29 17:58:20 -0700886
887 // Clear out the context mode views after the animation finishes
Adam Powell640a66e2011-04-29 10:18:53 -0700888 mContextView.closeMode();
Adam Powell86ed4362011-09-14 16:18:53 -0700889 mActionView.sendAccessibilityEvent(AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED);
Adam Powellf6ce6a92011-06-29 10:25:01 -0700890
Adam Powell5d279772010-07-27 16:34:07 -0700891 mActionMode = null;
Adam Powell89e06452010-06-23 20:24:52 -0700892 }
893
894 @Override
895 public void invalidate() {
Adam Powell5ee36c42011-06-02 12:59:43 -0700896 mMenu.stopDispatchingItemsChanged();
897 try {
898 mCallback.onPrepareActionMode(this, mMenu);
899 } finally {
900 mMenu.startDispatchingItemsChanged();
901 }
902 }
903
904 public boolean dispatchOnCreate() {
905 mMenu.stopDispatchingItemsChanged();
906 try {
907 return mCallback.onCreateActionMode(this, mMenu);
908 } finally {
909 mMenu.startDispatchingItemsChanged();
Adam Powell89e06452010-06-23 20:24:52 -0700910 }
911 }
912
913 @Override
914 public void setCustomView(View view) {
Adam Powell640a66e2011-04-29 10:18:53 -0700915 mContextView.setCustomView(view);
Adam Powell29ed7572010-07-14 16:24:56 -0700916 mCustomView = new WeakReference<View>(view);
Adam Powell89e06452010-06-23 20:24:52 -0700917 }
918
919 @Override
920 public void setSubtitle(CharSequence subtitle) {
Adam Powell640a66e2011-04-29 10:18:53 -0700921 mContextView.setSubtitle(subtitle);
Adam Powell89e06452010-06-23 20:24:52 -0700922 }
923
924 @Override
925 public void setTitle(CharSequence title) {
Adam Powell640a66e2011-04-29 10:18:53 -0700926 mContextView.setTitle(title);
Adam Powell89e06452010-06-23 20:24:52 -0700927 }
Adam Powell29ed7572010-07-14 16:24:56 -0700928
929 @Override
Adam Powellc9ae2a22010-07-28 14:44:21 -0700930 public void setTitle(int resId) {
Adam Powell48e8ac32011-01-14 12:10:24 -0800931 setTitle(mContext.getResources().getString(resId));
Adam Powellc9ae2a22010-07-28 14:44:21 -0700932 }
933
934 @Override
935 public void setSubtitle(int resId) {
Adam Powell48e8ac32011-01-14 12:10:24 -0800936 setSubtitle(mContext.getResources().getString(resId));
Adam Powellc9ae2a22010-07-28 14:44:21 -0700937 }
938
939 @Override
Adam Powell29ed7572010-07-14 16:24:56 -0700940 public CharSequence getTitle() {
Adam Powell640a66e2011-04-29 10:18:53 -0700941 return mContextView.getTitle();
Adam Powell29ed7572010-07-14 16:24:56 -0700942 }
943
944 @Override
945 public CharSequence getSubtitle() {
Adam Powell640a66e2011-04-29 10:18:53 -0700946 return mContextView.getSubtitle();
Adam Powell29ed7572010-07-14 16:24:56 -0700947 }
Adam Powell89e06452010-06-23 20:24:52 -0700948
Adam Powell29ed7572010-07-14 16:24:56 -0700949 @Override
Adam Powellb98a81f2012-02-24 11:09:07 -0800950 public void setTitleOptionalHint(boolean titleOptional) {
Adam Powell785c4472012-05-02 21:25:39 -0700951 super.setTitleOptionalHint(titleOptional);
Adam Powellb98a81f2012-02-24 11:09:07 -0800952 mContextView.setTitleOptional(titleOptional);
953 }
954
955 @Override
956 public boolean isTitleOptional() {
957 return mContextView.isTitleOptional();
958 }
959
960 @Override
Adam Powell29ed7572010-07-14 16:24:56 -0700961 public View getCustomView() {
962 return mCustomView != null ? mCustomView.get() : null;
963 }
964
Adam Powell2c9c9fe2010-07-16 10:17:57 -0700965 public boolean onMenuItemSelected(MenuBuilder menu, MenuItem item) {
Adam Powelld8b3f2e2010-12-02 13:37:03 -0800966 if (mCallback != null) {
967 return mCallback.onActionItemClicked(this, item);
968 } else {
969 return false;
970 }
Adam Powell2c9c9fe2010-07-16 10:17:57 -0700971 }
972
973 public void onCloseMenu(MenuBuilder menu, boolean allMenusAreClosing) {
974 }
975
976 public boolean onSubMenuSelected(SubMenuBuilder subMenu) {
Adam Powelld8b3f2e2010-12-02 13:37:03 -0800977 if (mCallback == null) {
978 return false;
979 }
980
Adam Powell2c9c9fe2010-07-16 10:17:57 -0700981 if (!subMenu.hasVisibleItems()) {
982 return true;
Adam Powell89e06452010-06-23 20:24:52 -0700983 }
Adam Powell2c9c9fe2010-07-16 10:17:57 -0700984
Adam Powellf2423682011-08-11 14:29:45 -0700985 new MenuPopupHelper(getThemedContext(), subMenu).show();
Adam Powell2c9c9fe2010-07-16 10:17:57 -0700986 return true;
987 }
988
989 public void onCloseSubMenu(SubMenuBuilder menu) {
990 }
991
992 public void onMenuModeChange(MenuBuilder menu) {
Adam Powelld8b3f2e2010-12-02 13:37:03 -0800993 if (mCallback == null) {
994 return;
995 }
Adam Powellf6148c52010-08-11 21:10:16 -0700996 invalidate();
Adam Powell640a66e2011-04-29 10:18:53 -0700997 mContextView.showOverflowMenu();
Adam Powell2c9c9fe2010-07-16 10:17:57 -0700998 }
Adam Powell661c9082010-07-02 10:09:44 -0700999 }
1000
1001 /**
1002 * @hide
1003 */
1004 public class TabImpl extends ActionBar.Tab {
Adam Powell2b6230e2010-09-07 17:55:25 -07001005 private ActionBar.TabListener mCallback;
1006 private Object mTag;
Adam Powell661c9082010-07-02 10:09:44 -07001007 private Drawable mIcon;
1008 private CharSequence mText;
Adam Powell94e56ef2011-09-06 21:22:22 -07001009 private CharSequence mContentDesc;
Adam Powell0d8ec1d2011-05-03 14:49:13 -07001010 private int mPosition = -1;
Adam Powell2b6230e2010-09-07 17:55:25 -07001011 private View mCustomView;
Adam Powell661c9082010-07-02 10:09:44 -07001012
1013 @Override
Adam Powell2b6230e2010-09-07 17:55:25 -07001014 public Object getTag() {
1015 return mTag;
1016 }
1017
1018 @Override
Adam Powell9ab97872010-10-26 21:47:29 -07001019 public Tab setTag(Object tag) {
Adam Powell2b6230e2010-09-07 17:55:25 -07001020 mTag = tag;
Adam Powell9ab97872010-10-26 21:47:29 -07001021 return this;
Adam Powell2b6230e2010-09-07 17:55:25 -07001022 }
1023
1024 public ActionBar.TabListener getCallback() {
1025 return mCallback;
1026 }
1027
1028 @Override
Adam Powell9ab97872010-10-26 21:47:29 -07001029 public Tab setTabListener(ActionBar.TabListener callback) {
Adam Powell2b6230e2010-09-07 17:55:25 -07001030 mCallback = callback;
Adam Powell9ab97872010-10-26 21:47:29 -07001031 return this;
Adam Powell2b6230e2010-09-07 17:55:25 -07001032 }
1033
1034 @Override
1035 public View getCustomView() {
1036 return mCustomView;
1037 }
1038
1039 @Override
Adam Powell9ab97872010-10-26 21:47:29 -07001040 public Tab setCustomView(View view) {
Adam Powell2b6230e2010-09-07 17:55:25 -07001041 mCustomView = view;
Adam Powellf8ac6b72011-05-23 18:14:09 -07001042 if (mPosition >= 0) {
1043 mTabScrollView.updateTab(mPosition);
1044 }
Adam Powell9ab97872010-10-26 21:47:29 -07001045 return this;
Adam Powell661c9082010-07-02 10:09:44 -07001046 }
1047
1048 @Override
Adam Powell32555f32010-11-17 13:49:22 -08001049 public Tab setCustomView(int layoutResId) {
Adam Powellf2423682011-08-11 14:29:45 -07001050 return setCustomView(LayoutInflater.from(getThemedContext())
1051 .inflate(layoutResId, null));
Adam Powell32555f32010-11-17 13:49:22 -08001052 }
1053
1054 @Override
Adam Powell661c9082010-07-02 10:09:44 -07001055 public Drawable getIcon() {
1056 return mIcon;
1057 }
1058
1059 @Override
1060 public int getPosition() {
1061 return mPosition;
1062 }
1063
1064 public void setPosition(int position) {
1065 mPosition = position;
1066 }
1067
1068 @Override
1069 public CharSequence getText() {
1070 return mText;
1071 }
1072
1073 @Override
Adam Powell9ab97872010-10-26 21:47:29 -07001074 public Tab setIcon(Drawable icon) {
Adam Powell661c9082010-07-02 10:09:44 -07001075 mIcon = icon;
Adam Powellf8ac6b72011-05-23 18:14:09 -07001076 if (mPosition >= 0) {
1077 mTabScrollView.updateTab(mPosition);
1078 }
Adam Powell9ab97872010-10-26 21:47:29 -07001079 return this;
Adam Powell661c9082010-07-02 10:09:44 -07001080 }
1081
1082 @Override
Adam Powell32555f32010-11-17 13:49:22 -08001083 public Tab setIcon(int resId) {
Alan Viverette8eea3ea2014-02-03 18:40:20 -08001084 return setIcon(mContext.getDrawable(resId));
Adam Powell32555f32010-11-17 13:49:22 -08001085 }
1086
1087 @Override
Adam Powell9ab97872010-10-26 21:47:29 -07001088 public Tab setText(CharSequence text) {
Adam Powell661c9082010-07-02 10:09:44 -07001089 mText = text;
Adam Powellf8ac6b72011-05-23 18:14:09 -07001090 if (mPosition >= 0) {
1091 mTabScrollView.updateTab(mPosition);
1092 }
Adam Powell9ab97872010-10-26 21:47:29 -07001093 return this;
Adam Powell661c9082010-07-02 10:09:44 -07001094 }
1095
1096 @Override
Adam Powell32555f32010-11-17 13:49:22 -08001097 public Tab setText(int resId) {
1098 return setText(mContext.getResources().getText(resId));
1099 }
1100
1101 @Override
Adam Powell661c9082010-07-02 10:09:44 -07001102 public void select() {
1103 selectTab(this);
Adam Powell89e06452010-06-23 20:24:52 -07001104 }
Adam Powell94e56ef2011-09-06 21:22:22 -07001105
1106 @Override
1107 public Tab setContentDescription(int resId) {
1108 return setContentDescription(mContext.getResources().getText(resId));
1109 }
1110
1111 @Override
1112 public Tab setContentDescription(CharSequence contentDesc) {
1113 mContentDesc = contentDesc;
1114 if (mPosition >= 0) {
1115 mTabScrollView.updateTab(mPosition);
1116 }
1117 return this;
1118 }
1119
1120 @Override
1121 public CharSequence getContentDescription() {
1122 return mContentDesc;
1123 }
Adam Powell89e06452010-06-23 20:24:52 -07001124 }
Adam Powell9ab97872010-10-26 21:47:29 -07001125
1126 @Override
1127 public void setCustomView(View view) {
1128 mActionView.setCustomNavigationView(view);
1129 }
1130
1131 @Override
1132 public void setCustomView(View view, LayoutParams layoutParams) {
1133 view.setLayoutParams(layoutParams);
1134 mActionView.setCustomNavigationView(view);
1135 }
1136
1137 @Override
Adam Powell8515ee82010-11-30 14:09:55 -08001138 public void setListNavigationCallbacks(SpinnerAdapter adapter, OnNavigationListener callback) {
Adam Powell9ab97872010-10-26 21:47:29 -07001139 mActionView.setDropdownAdapter(adapter);
1140 mActionView.setCallback(callback);
1141 }
1142
1143 @Override
1144 public int getSelectedNavigationIndex() {
1145 switch (mActionView.getNavigationMode()) {
1146 case NAVIGATION_MODE_TABS:
Adam Powell04587962010-11-11 22:15:07 -08001147 return mSelectedTab != null ? mSelectedTab.getPosition() : -1;
Adam Powell9ab97872010-10-26 21:47:29 -07001148 case NAVIGATION_MODE_LIST:
1149 return mActionView.getDropdownSelectedPosition();
1150 default:
1151 return -1;
1152 }
1153 }
1154
1155 @Override
1156 public int getNavigationItemCount() {
1157 switch (mActionView.getNavigationMode()) {
1158 case NAVIGATION_MODE_TABS:
1159 return mTabs.size();
1160 case NAVIGATION_MODE_LIST:
1161 SpinnerAdapter adapter = mActionView.getDropdownAdapter();
1162 return adapter != null ? adapter.getCount() : 0;
1163 default:
1164 return 0;
1165 }
1166 }
1167
1168 @Override
Adam Powell0c24a552010-11-03 16:44:11 -07001169 public int getTabCount() {
1170 return mTabs.size();
1171 }
1172
1173 @Override
Adam Powell9ab97872010-10-26 21:47:29 -07001174 public void setNavigationMode(int mode) {
Adam Powell0c24a552010-11-03 16:44:11 -07001175 final int oldMode = mActionView.getNavigationMode();
1176 switch (oldMode) {
1177 case NAVIGATION_MODE_TABS:
1178 mSavedTabPosition = getSelectedNavigationIndex();
1179 selectTab(null);
Adam Powellf5645cb2011-08-10 22:49:02 -07001180 mTabScrollView.setVisibility(View.GONE);
Adam Powell0c24a552010-11-03 16:44:11 -07001181 break;
1182 }
Dianne Hackborn3a3a6cf2012-03-26 10:24:04 -07001183 if (oldMode != mode && !mHasEmbeddedTabs) {
1184 if (mOverlayLayout != null) {
1185 mOverlayLayout.requestFitSystemWindows();
1186 }
1187 }
Adam Powell9ab97872010-10-26 21:47:29 -07001188 mActionView.setNavigationMode(mode);
Adam Powell0c24a552010-11-03 16:44:11 -07001189 switch (mode) {
1190 case NAVIGATION_MODE_TABS:
Adam Powellf8ac6b72011-05-23 18:14:09 -07001191 ensureTabsExist();
Adam Powellf5645cb2011-08-10 22:49:02 -07001192 mTabScrollView.setVisibility(View.VISIBLE);
Adam Powell0c24a552010-11-03 16:44:11 -07001193 if (mSavedTabPosition != INVALID_POSITION) {
1194 setSelectedNavigationItem(mSavedTabPosition);
1195 mSavedTabPosition = INVALID_POSITION;
1196 }
1197 break;
1198 }
Adam Powelld21aa122011-05-27 13:09:52 -07001199 mActionView.setCollapsable(mode == NAVIGATION_MODE_TABS && !mHasEmbeddedTabs);
Adam Powell9ab97872010-10-26 21:47:29 -07001200 }
1201
1202 @Override
1203 public Tab getTabAt(int index) {
1204 return mTabs.get(index);
1205 }
Adam Powell0c24a552010-11-03 16:44:11 -07001206
Adam Powell0c24a552010-11-03 16:44:11 -07001207
Adam Powell1969b872011-03-22 11:52:48 -07001208 @Override
1209 public void setIcon(int resId) {
Adam Powell45c515b2011-04-21 18:50:20 -07001210 mActionView.setIcon(resId);
Adam Powell1969b872011-03-22 11:52:48 -07001211 }
Adam Powell0c24a552010-11-03 16:44:11 -07001212
Adam Powell1969b872011-03-22 11:52:48 -07001213 @Override
1214 public void setIcon(Drawable icon) {
1215 mActionView.setIcon(icon);
1216 }
1217
Adam Powell04fe6eb2013-05-31 14:39:48 -07001218 public boolean hasIcon() {
1219 return mActionView.hasIcon();
1220 }
1221
Adam Powell1969b872011-03-22 11:52:48 -07001222 @Override
1223 public void setLogo(int resId) {
Adam Powell45c515b2011-04-21 18:50:20 -07001224 mActionView.setLogo(resId);
Adam Powell1969b872011-03-22 11:52:48 -07001225 }
1226
1227 @Override
1228 public void setLogo(Drawable logo) {
1229 mActionView.setLogo(logo);
Adam Powell0c24a552010-11-03 16:44:11 -07001230 }
Adam Powelldd8fab22012-03-22 17:47:27 -07001231
Adam Powell04fe6eb2013-05-31 14:39:48 -07001232 public boolean hasLogo() {
1233 return mActionView.hasLogo();
1234 }
1235
Adam Powelldd8fab22012-03-22 17:47:27 -07001236 public void setDefaultDisplayHomeAsUpEnabled(boolean enable) {
1237 if (!mDisplayHomeAsUpSet) {
1238 setDisplayHomeAsUpEnabled(enable);
1239 }
1240 }
Adam Powell89e06452010-06-23 20:24:52 -07001241}