blob: c6afae07ab5ac603e66efbdd87f39553a369fa64 [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;
George Mounte1803372014-02-26 19:00:52 +000060import java.util.Map;
Adam Powell661c9082010-07-02 10:09:44 -070061
Adam Powell89e06452010-06-23 20:24:52 -070062/**
Adam Powelle43340c2014-03-17 19:10:43 -070063 * WindowDecorActionBar is the ActionBar implementation used
64 * by devices of all screen sizes as part of the window decor layout.
65 * If it detects a compatible decor, it will split contextual modes
66 * across both the ActionBarView at the top of the screen and
67 * a horizontal LinearLayout at the bottom which is normally hidden.
Adam Powell89e06452010-06-23 20:24:52 -070068 */
Adam Powelle43340c2014-03-17 19:10:43 -070069public class WindowDecorActionBar extends ActionBar {
70 private static final String TAG = "WindowDecorActionBar";
Adam Powell661c9082010-07-02 10:09:44 -070071
Adam Powelldec9dfd2010-08-09 15:27:54 -070072 private Context mContext;
Adam Powell88ab6972011-07-28 11:25:01 -070073 private Context mThemedContext;
Adam Powell661c9082010-07-02 10:09:44 -070074 private Activity mActivity;
Adam Powelldec9dfd2010-08-09 15:27:54 -070075 private Dialog mDialog;
Adam Powell661c9082010-07-02 10:09:44 -070076
Dianne Hackborn3a3a6cf2012-03-26 10:24:04 -070077 private ActionBarOverlayLayout mOverlayLayout;
Adam Powell01feaee2011-02-10 15:05:05 -080078 private ActionBarContainer mContainerView;
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
Dianne Hackborn3a3a6cf2012-03-26 10:24:04 -0700108 private int mCurWindowVisibility = View.VISIBLE;
109
Dianne Hackborndf7221c2013-02-26 14:53:55 -0800110 private boolean mContentAnimations = true;
Dianne Hackborn139e5aa2012-05-05 20:36:38 -0700111 private boolean mHiddenByApp;
112 private boolean mHiddenBySystem;
113 private boolean mShowingForMode;
114
115 private boolean mNowShowing = true;
116
Adam Powell07e1f982011-03-24 11:11:15 -0700117 private Animator mCurrentShowAnim;
Adam Powell50efbed2011-02-08 16:20:15 -0800118 private boolean mShowHideAnimationEnabled;
Adam Powelld8b3f2e2010-12-02 13:37:03 -0800119
Adam Powell07e1f982011-03-24 11:11:15 -0700120 final AnimatorListener mHideListener = new AnimatorListenerAdapter() {
Adam Powelle6ec7322010-12-07 15:29:26 -0800121 @Override
122 public void onAnimationEnd(Animator animation) {
Dianne Hackborndf7221c2013-02-26 14:53:55 -0800123 if (mContentAnimations && mContentView != null) {
Adam Powelle6ec7322010-12-07 15:29:26 -0800124 mContentView.setTranslationY(0);
Adam Powell9b0dc282013-07-31 13:58:43 -0700125 mContainerView.setTranslationY(0);
Adam Powelle6ec7322010-12-07 15:29:26 -0800126 }
Adam Powell993a63a2011-08-18 16:35:53 -0700127 if (mSplitView != null && mContextDisplayMode == CONTEXT_DISPLAY_SPLIT) {
128 mSplitView.setVisibility(View.GONE);
129 }
Adam Powell9b0dc282013-07-31 13:58:43 -0700130 mContainerView.setVisibility(View.GONE);
Adam Powell01feaee2011-02-10 15:05:05 -0800131 mContainerView.setTransitioning(false);
Adam Powell07e1f982011-03-24 11:11:15 -0700132 mCurrentShowAnim = null;
Adam Powell060e3ca2011-07-19 20:39:16 -0700133 completeDeferredDestroyActionMode();
Dianne Hackborn139e5aa2012-05-05 20:36:38 -0700134 if (mOverlayLayout != null) {
135 mOverlayLayout.requestFitSystemWindows();
136 }
Adam Powelle6ec7322010-12-07 15:29:26 -0800137 }
138 };
139
Adam Powell07e1f982011-03-24 11:11:15 -0700140 final AnimatorListener mShowListener = new AnimatorListenerAdapter() {
Adam Powelle6ec7322010-12-07 15:29:26 -0800141 @Override
142 public void onAnimationEnd(Animator animation) {
Adam Powell07e1f982011-03-24 11:11:15 -0700143 mCurrentShowAnim = null;
Adam Powell9b0dc282013-07-31 13:58:43 -0700144 mContainerView.requestLayout();
145 }
146 };
147
148 final ValueAnimator.AnimatorUpdateListener mUpdateListener =
149 new ValueAnimator.AnimatorUpdateListener() {
150 @Override
151 public void onAnimationUpdate(ValueAnimator animation) {
152 final ViewParent parent = mContainerView.getParent();
153 ((View) parent).invalidate();
Adam Powelle6ec7322010-12-07 15:29:26 -0800154 }
Adam Powelle6ec7322010-12-07 15:29:26 -0800155 };
156
Adam Powelle43340c2014-03-17 19:10:43 -0700157 public WindowDecorActionBar(Activity activity) {
Adam Powell661c9082010-07-02 10:09:44 -0700158 mActivity = activity;
Adam Powelle6ec7322010-12-07 15:29:26 -0800159 Window window = activity.getWindow();
160 View decor = window.getDecorView();
Dianne Hackborndf7221c2013-02-26 14:53:55 -0800161 boolean overlayMode = mActivity.getWindow().hasFeature(Window.FEATURE_ACTION_BAR_OVERLAY);
Adam Powell9b0dc282013-07-31 13:58:43 -0700162 init(decor);
Dianne Hackborndf7221c2013-02-26 14:53:55 -0800163 if (!overlayMode) {
Adam Powelle6ec7322010-12-07 15:29:26 -0800164 mContentView = decor.findViewById(android.R.id.content);
165 }
Adam Powelldec9dfd2010-08-09 15:27:54 -0700166 }
167
Adam Powelle43340c2014-03-17 19:10:43 -0700168 public WindowDecorActionBar(Dialog dialog) {
Adam Powelldec9dfd2010-08-09 15:27:54 -0700169 mDialog = dialog;
Adam Powell9b0dc282013-07-31 13:58:43 -0700170 init(dialog.getWindow().getDecorView());
Adam Powelldec9dfd2010-08-09 15:27:54 -0700171 }
172
Adam Powell9b0dc282013-07-31 13:58:43 -0700173 private void init(View decor) {
Dianne Hackborn3a3a6cf2012-03-26 10:24:04 -0700174 mOverlayLayout = (ActionBarOverlayLayout) decor.findViewById(
175 com.android.internal.R.id.action_bar_overlay_layout);
176 if (mOverlayLayout != null) {
Adam Powell9b0dc282013-07-31 13:58:43 -0700177 mOverlayLayout.setActionBar(this);
Dianne Hackborn3a3a6cf2012-03-26 10:24:04 -0700178 }
Adam Powell89e06452010-06-23 20:24:52 -0700179 mActionView = (ActionBarView) decor.findViewById(com.android.internal.R.id.action_bar);
Adam Powell640a66e2011-04-29 10:18:53 -0700180 mContextView = (ActionBarContextView) decor.findViewById(
Adam Powell89e06452010-06-23 20:24:52 -0700181 com.android.internal.R.id.action_context_bar);
Adam Powell01feaee2011-02-10 15:05:05 -0800182 mContainerView = (ActionBarContainer) decor.findViewById(
Adam Powelld8b3f2e2010-12-02 13:37:03 -0800183 com.android.internal.R.id.action_bar_container);
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
Alan Viverette62599332014-04-01 14:57:39 -0700192 mContext = mActionView.getContext();
Adam Powell640a66e2011-04-29 10:18:53 -0700193 mActionView.setContextView(mContextView);
Adam Powell9b4bee02011-04-27 19:24:47 -0700194 mContextDisplayMode = mActionView.isSplitActionBar() ?
195 CONTEXT_DISPLAY_SPLIT : CONTEXT_DISPLAY_NORMAL;
Adam Powelldae78242011-04-25 15:23:41 -0700196
Adam Powelld40423a2012-05-02 14:06:03 -0700197 // This was initially read from the action bar style
198 final int current = mActionView.getDisplayOptions();
199 final boolean homeAsUp = (current & DISPLAY_HOME_AS_UP) != 0;
200 if (homeAsUp) {
201 mDisplayHomeAsUpSet = true;
202 }
203
Adam Powellb8139af2012-04-19 13:52:46 -0700204 ActionBarPolicy abp = ActionBarPolicy.get(mContext);
Adam Powelld40423a2012-05-02 14:06:03 -0700205 setHomeButtonEnabled(abp.enableHomeButtonByDefault() || homeAsUp);
Adam Powellb8139af2012-04-19 13:52:46 -0700206 setHasEmbeddedTabs(abp.hasEmbeddedTabs());
Adam Powellf8ac6b72011-05-23 18:14:09 -0700207 }
208
209 public void onConfigurationChanged(Configuration newConfig) {
Adam Powellb8139af2012-04-19 13:52:46 -0700210 setHasEmbeddedTabs(ActionBarPolicy.get(mContext).hasEmbeddedTabs());
Adam Powellf5645cb2011-08-10 22:49:02 -0700211 }
Adam Powellf8ac6b72011-05-23 18:14:09 -0700212
Adam Powellf5645cb2011-08-10 22:49:02 -0700213 private void setHasEmbeddedTabs(boolean hasEmbeddedTabs) {
214 mHasEmbeddedTabs = hasEmbeddedTabs;
Adam Powellf8ac6b72011-05-23 18:14:09 -0700215 // Switch tab layout configuration if needed
216 if (!mHasEmbeddedTabs) {
217 mActionView.setEmbeddedTabView(null);
218 mContainerView.setTabContainer(mTabScrollView);
219 } else {
220 mContainerView.setTabContainer(null);
Adam Powellf8ac6b72011-05-23 18:14:09 -0700221 mActionView.setEmbeddedTabView(mTabScrollView);
222 }
Adam Powellf5645cb2011-08-10 22:49:02 -0700223 final boolean isInTabMode = getNavigationMode() == NAVIGATION_MODE_TABS;
224 if (mTabScrollView != null) {
Dianne Hackborn3a3a6cf2012-03-26 10:24:04 -0700225 if (isInTabMode) {
226 mTabScrollView.setVisibility(View.VISIBLE);
227 if (mOverlayLayout != null) {
228 mOverlayLayout.requestFitSystemWindows();
229 }
230 } else {
231 mTabScrollView.setVisibility(View.GONE);
232 }
Adam Powellf5645cb2011-08-10 22:49:02 -0700233 }
234 mActionView.setCollapsable(!mHasEmbeddedTabs && isInTabMode);
Adam Powellf8ac6b72011-05-23 18:14:09 -0700235 }
236
Dianne Hackborn3a3a6cf2012-03-26 10:24:04 -0700237 public boolean hasNonEmbeddedTabs() {
238 return !mHasEmbeddedTabs && getNavigationMode() == NAVIGATION_MODE_TABS;
239 }
240
Adam Powellf8ac6b72011-05-23 18:14:09 -0700241 private void ensureTabsExist() {
242 if (mTabScrollView != null) {
243 return;
244 }
245
Adam Powellf5645cb2011-08-10 22:49:02 -0700246 ScrollingTabContainerView tabScroller = new ScrollingTabContainerView(mContext);
Adam Powellf8ac6b72011-05-23 18:14:09 -0700247
248 if (mHasEmbeddedTabs) {
249 tabScroller.setVisibility(View.VISIBLE);
250 mActionView.setEmbeddedTabView(tabScroller);
251 } else {
Dianne Hackborn3a3a6cf2012-03-26 10:24:04 -0700252 if (getNavigationMode() == NAVIGATION_MODE_TABS) {
253 tabScroller.setVisibility(View.VISIBLE);
254 if (mOverlayLayout != null) {
255 mOverlayLayout.requestFitSystemWindows();
256 }
257 } else {
258 tabScroller.setVisibility(View.GONE);
259 }
Adam Powelldae78242011-04-25 15:23:41 -0700260 mContainerView.setTabContainer(tabScroller);
Adam Powelldae78242011-04-25 15:23:41 -0700261 }
Adam Powellf8ac6b72011-05-23 18:14:09 -0700262 mTabScrollView = tabScroller;
Adam Powell89e06452010-06-23 20:24:52 -0700263 }
264
Adam Powell060e3ca2011-07-19 20:39:16 -0700265 void completeDeferredDestroyActionMode() {
266 if (mDeferredModeDestroyCallback != null) {
267 mDeferredModeDestroyCallback.onDestroyActionMode(mDeferredDestroyActionMode);
268 mDeferredDestroyActionMode = null;
269 mDeferredModeDestroyCallback = null;
270 }
271 }
272
Dianne Hackborn3a3a6cf2012-03-26 10:24:04 -0700273 public void setWindowVisibility(int visibility) {
274 mCurWindowVisibility = visibility;
275 }
276
Adam Powell50efbed2011-02-08 16:20:15 -0800277 /**
278 * Enables or disables animation between show/hide states.
279 * If animation is disabled using this method, animations in progress
280 * will be finished.
281 *
282 * @param enabled true to animate, false to not animate.
283 */
284 public void setShowHideAnimationEnabled(boolean enabled) {
285 mShowHideAnimationEnabled = enabled;
Adam Powell07e1f982011-03-24 11:11:15 -0700286 if (!enabled && mCurrentShowAnim != null) {
287 mCurrentShowAnim.end();
Adam Powell50efbed2011-02-08 16:20:15 -0800288 }
289 }
290
Adam Powell8515ee82010-11-30 14:09:55 -0800291 public void addOnMenuVisibilityListener(OnMenuVisibilityListener listener) {
292 mMenuVisibilityListeners.add(listener);
293 }
294
295 public void removeOnMenuVisibilityListener(OnMenuVisibilityListener listener) {
296 mMenuVisibilityListeners.remove(listener);
297 }
298
299 public void dispatchMenuVisibilityChanged(boolean isVisible) {
300 if (isVisible == mLastMenuVisibility) {
301 return;
302 }
303 mLastMenuVisibility = isVisible;
304
305 final int count = mMenuVisibilityListeners.size();
306 for (int i = 0; i < count; i++) {
307 mMenuVisibilityListeners.get(i).onMenuVisibilityChanged(isVisible);
308 }
309 }
310
Adam Powella66c7b02010-07-28 15:28:25 -0700311 @Override
Adam Powell3f476b32011-01-03 19:25:36 -0800312 public void setCustomView(int resId) {
Adam Powellf2423682011-08-11 14:29:45 -0700313 setCustomView(LayoutInflater.from(getThemedContext()).inflate(resId, mActionView, false));
Adam Powell3f476b32011-01-03 19:25:36 -0800314 }
315
316 @Override
317 public void setDisplayUseLogoEnabled(boolean useLogo) {
318 setDisplayOptions(useLogo ? DISPLAY_USE_LOGO : 0, DISPLAY_USE_LOGO);
319 }
320
321 @Override
322 public void setDisplayShowHomeEnabled(boolean showHome) {
323 setDisplayOptions(showHome ? DISPLAY_SHOW_HOME : 0, DISPLAY_SHOW_HOME);
324 }
325
326 @Override
327 public void setDisplayHomeAsUpEnabled(boolean showHomeAsUp) {
328 setDisplayOptions(showHomeAsUp ? DISPLAY_HOME_AS_UP : 0, DISPLAY_HOME_AS_UP);
329 }
330
331 @Override
332 public void setDisplayShowTitleEnabled(boolean showTitle) {
333 setDisplayOptions(showTitle ? DISPLAY_SHOW_TITLE : 0, DISPLAY_SHOW_TITLE);
334 }
335
336 @Override
337 public void setDisplayShowCustomEnabled(boolean showCustom) {
338 setDisplayOptions(showCustom ? DISPLAY_SHOW_CUSTOM : 0, DISPLAY_SHOW_CUSTOM);
339 }
340
341 @Override
Adam Powellc29f4e52011-07-13 20:40:52 -0700342 public void setHomeButtonEnabled(boolean enable) {
343 mActionView.setHomeButtonEnabled(enable);
Adam Powelldae78242011-04-25 15:23:41 -0700344 }
345
346 @Override
Adam Powella66c7b02010-07-28 15:28:25 -0700347 public void setTitle(int resId) {
Adam Powelldec9dfd2010-08-09 15:27:54 -0700348 setTitle(mContext.getString(resId));
Adam Powella66c7b02010-07-28 15:28:25 -0700349 }
350
351 @Override
352 public void setSubtitle(int resId) {
Adam Powelldec9dfd2010-08-09 15:27:54 -0700353 setSubtitle(mContext.getString(resId));
Adam Powella66c7b02010-07-28 15:28:25 -0700354 }
355
George Mounte1803372014-02-26 19:00:52 +0000356 public void captureSharedElements(Map<String, View> sharedElements) {
357 mContainerView.findSharedElements(sharedElements);
358 }
359
Adam Powell17809772010-07-21 13:25:11 -0700360 public void setSelectedNavigationItem(int position) {
361 switch (mActionView.getNavigationMode()) {
362 case NAVIGATION_MODE_TABS:
363 selectTab(mTabs.get(position));
364 break;
Adam Powell9ab97872010-10-26 21:47:29 -0700365 case NAVIGATION_MODE_LIST:
Adam Powell17809772010-07-21 13:25:11 -0700366 mActionView.setDropdownSelectedPosition(position);
367 break;
368 default:
369 throw new IllegalStateException(
Adam Powell9ab97872010-10-26 21:47:29 -0700370 "setSelectedNavigationIndex not valid for current navigation mode");
Adam Powell17809772010-07-21 13:25:11 -0700371 }
372 }
373
Adam Powell9ab97872010-10-26 21:47:29 -0700374 public void removeAllTabs() {
375 cleanupTabs();
Adam Powell17809772010-07-21 13:25:11 -0700376 }
377
Adam Powell661c9082010-07-02 10:09:44 -0700378 private void cleanupTabs() {
379 if (mSelectedTab != null) {
380 selectTab(null);
381 }
Adam Powell2b6230e2010-09-07 17:55:25 -0700382 mTabs.clear();
Adam Powelld21aa122011-05-27 13:09:52 -0700383 if (mTabScrollView != null) {
384 mTabScrollView.removeAllTabs();
385 }
Adam Powell0c24a552010-11-03 16:44:11 -0700386 mSavedTabPosition = INVALID_POSITION;
Adam Powell661c9082010-07-02 10:09:44 -0700387 }
388
Adam Powell0e94b512010-06-29 17:58:20 -0700389 public void setTitle(CharSequence title) {
390 mActionView.setTitle(title);
391 }
392
393 public void setSubtitle(CharSequence subtitle) {
394 mActionView.setSubtitle(subtitle);
395 }
396
Adam Powell89e06452010-06-23 20:24:52 -0700397 public void setDisplayOptions(int options) {
Adam Powelldd8fab22012-03-22 17:47:27 -0700398 if ((options & DISPLAY_HOME_AS_UP) != 0) {
399 mDisplayHomeAsUpSet = true;
400 }
Adam Powell89e06452010-06-23 20:24:52 -0700401 mActionView.setDisplayOptions(options);
402 }
Adam Powell0e94b512010-06-29 17:58:20 -0700403
Adam Powell89e06452010-06-23 20:24:52 -0700404 public void setDisplayOptions(int options, int mask) {
405 final int current = mActionView.getDisplayOptions();
Adam Powelldd8fab22012-03-22 17:47:27 -0700406 if ((mask & DISPLAY_HOME_AS_UP) != 0) {
407 mDisplayHomeAsUpSet = true;
408 }
Adam Powell89e06452010-06-23 20:24:52 -0700409 mActionView.setDisplayOptions((options & mask) | (current & ~mask));
410 }
411
412 public void setBackgroundDrawable(Drawable d) {
Adam Powellf88b9152011-09-07 14:54:32 -0700413 mContainerView.setPrimaryBackground(d);
414 }
415
416 public void setStackedBackgroundDrawable(Drawable d) {
417 mContainerView.setStackedBackground(d);
418 }
419
420 public void setSplitBackgroundDrawable(Drawable d) {
421 if (mSplitView != null) {
422 mSplitView.setSplitBackground(d);
423 }
Adam Powell89e06452010-06-23 20:24:52 -0700424 }
425
Adam Powellef704442010-11-16 14:48:22 -0800426 public View getCustomView() {
Adam Powell89e06452010-06-23 20:24:52 -0700427 return mActionView.getCustomNavigationView();
428 }
429
430 public CharSequence getTitle() {
431 return mActionView.getTitle();
432 }
433
434 public CharSequence getSubtitle() {
435 return mActionView.getSubtitle();
436 }
437
438 public int getNavigationMode() {
439 return mActionView.getNavigationMode();
440 }
441
442 public int getDisplayOptions() {
443 return mActionView.getDisplayOptions();
444 }
445
Adam Powell5d279772010-07-27 16:34:07 -0700446 public ActionMode startActionMode(ActionMode.Callback callback) {
447 if (mActionMode != null) {
448 mActionMode.finish();
Adam Powell6e346362010-07-23 10:18:23 -0700449 }
Adam Powell3461b322010-07-14 11:34:43 -0700450
Adam Powell640a66e2011-04-29 10:18:53 -0700451 mContextView.killMode();
Adam Powell5ee36c42011-06-02 12:59:43 -0700452 ActionModeImpl mode = new ActionModeImpl(callback);
453 if (mode.dispatchOnCreate()) {
Adam Powell2c9c9fe2010-07-16 10:17:57 -0700454 mode.invalidate();
Adam Powell640a66e2011-04-29 10:18:53 -0700455 mContextView.initForMode(mode);
456 animateToMode(true);
Adam Powell1ab418a2011-06-09 20:49:49 -0700457 if (mSplitView != null && mContextDisplayMode == CONTEXT_DISPLAY_SPLIT) {
Adam Powell89e06452010-06-23 20:24:52 -0700458 // TODO animate this
Dianne Hackborn3a3a6cf2012-03-26 10:24:04 -0700459 if (mSplitView.getVisibility() != View.VISIBLE) {
460 mSplitView.setVisibility(View.VISIBLE);
461 if (mOverlayLayout != null) {
462 mOverlayLayout.requestFitSystemWindows();
463 }
464 }
Adam Powell89e06452010-06-23 20:24:52 -0700465 }
Adam Powell86ed4362011-09-14 16:18:53 -0700466 mContextView.sendAccessibilityEvent(AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED);
Adam Powell5d279772010-07-27 16:34:07 -0700467 mActionMode = mode;
Adam Powellac695c62010-07-20 18:19:27 -0700468 return mode;
Adam Powell89e06452010-06-23 20:24:52 -0700469 }
Adam Powellac695c62010-07-20 18:19:27 -0700470 return null;
Adam Powell89e06452010-06-23 20:24:52 -0700471 }
472
Adam Powell661c9082010-07-02 10:09:44 -0700473 private void configureTab(Tab tab, int position) {
474 final TabImpl tabi = (TabImpl) tab;
Adam Powell2b6230e2010-09-07 17:55:25 -0700475 final ActionBar.TabListener callback = tabi.getCallback();
476
477 if (callback == null) {
478 throw new IllegalStateException("Action Bar Tab must have a Callback");
479 }
Adam Powell661c9082010-07-02 10:09:44 -0700480
481 tabi.setPosition(position);
482 mTabs.add(position, tabi);
483
Adam Powell81b89442010-11-02 17:58:56 -0700484 final int count = mTabs.size();
485 for (int i = position + 1; i < count; i++) {
486 mTabs.get(i).setPosition(i);
Adam Powell661c9082010-07-02 10:09:44 -0700487 }
Adam Powell661c9082010-07-02 10:09:44 -0700488 }
489
490 @Override
491 public void addTab(Tab tab) {
Adam Powell81b89442010-11-02 17:58:56 -0700492 addTab(tab, mTabs.isEmpty());
Adam Powell661c9082010-07-02 10:09:44 -0700493 }
494
495 @Override
Adam Powell2b6230e2010-09-07 17:55:25 -0700496 public void addTab(Tab tab, int position) {
Adam Powell81b89442010-11-02 17:58:56 -0700497 addTab(tab, position, mTabs.isEmpty());
498 }
499
500 @Override
501 public void addTab(Tab tab, boolean setSelected) {
Adam Powellf8ac6b72011-05-23 18:14:09 -0700502 ensureTabsExist();
503 mTabScrollView.addTab(tab, setSelected);
Adam Powell81b89442010-11-02 17:58:56 -0700504 configureTab(tab, mTabs.size());
505 if (setSelected) {
506 selectTab(tab);
507 }
508 }
509
510 @Override
511 public void addTab(Tab tab, int position, boolean setSelected) {
Adam Powellf8ac6b72011-05-23 18:14:09 -0700512 ensureTabsExist();
513 mTabScrollView.addTab(tab, position, setSelected);
Adam Powell661c9082010-07-02 10:09:44 -0700514 configureTab(tab, position);
Adam Powell81b89442010-11-02 17:58:56 -0700515 if (setSelected) {
516 selectTab(tab);
517 }
Adam Powell661c9082010-07-02 10:09:44 -0700518 }
519
520 @Override
521 public Tab newTab() {
522 return new TabImpl();
523 }
524
525 @Override
526 public void removeTab(Tab tab) {
527 removeTabAt(tab.getPosition());
528 }
529
530 @Override
531 public void removeTabAt(int position) {
Adam Powellf8ac6b72011-05-23 18:14:09 -0700532 if (mTabScrollView == null) {
533 // No tabs around to remove
534 return;
535 }
536
Adam Powell0c24a552010-11-03 16:44:11 -0700537 int selectedTabPosition = mSelectedTab != null
538 ? mSelectedTab.getPosition() : mSavedTabPosition;
Adam Powellf8ac6b72011-05-23 18:14:09 -0700539 mTabScrollView.removeTabAt(position);
Adam Powell0d8ec1d2011-05-03 14:49:13 -0700540 TabImpl removedTab = mTabs.remove(position);
541 if (removedTab != null) {
542 removedTab.setPosition(-1);
543 }
Adam Powell661c9082010-07-02 10:09:44 -0700544
545 final int newTabCount = mTabs.size();
546 for (int i = position; i < newTabCount; i++) {
547 mTabs.get(i).setPosition(i);
548 }
549
Adam Powell0c24a552010-11-03 16:44:11 -0700550 if (selectedTabPosition == position) {
551 selectTab(mTabs.isEmpty() ? null : mTabs.get(Math.max(0, position - 1)));
552 }
Adam Powell661c9082010-07-02 10:09:44 -0700553 }
554
555 @Override
Adam Powell661c9082010-07-02 10:09:44 -0700556 public void selectTab(Tab tab) {
Adam Powell0c24a552010-11-03 16:44:11 -0700557 if (getNavigationMode() != NAVIGATION_MODE_TABS) {
558 mSavedTabPosition = tab != null ? tab.getPosition() : INVALID_POSITION;
559 return;
560 }
561
Dianne Hackborn48e7b452011-01-17 12:28:35 -0800562 final FragmentTransaction trans = mActivity.getFragmentManager().beginTransaction()
Adam Powell0c24a552010-11-03 16:44:11 -0700563 .disallowAddToBackStack();
Adam Powell7f9b9052010-10-19 16:56:07 -0700564
565 if (mSelectedTab == tab) {
566 if (mSelectedTab != null) {
567 mSelectedTab.getCallback().onTabReselected(mSelectedTab, trans);
Adam Powellf8ac6b72011-05-23 18:14:09 -0700568 mTabScrollView.animateToTab(tab.getPosition());
Adam Powell7f9b9052010-10-19 16:56:07 -0700569 }
570 } else {
Adam Powellf8ac6b72011-05-23 18:14:09 -0700571 mTabScrollView.setTabSelected(tab != null ? tab.getPosition() : Tab.INVALID_POSITION);
Adam Powell7f9b9052010-10-19 16:56:07 -0700572 if (mSelectedTab != null) {
573 mSelectedTab.getCallback().onTabUnselected(mSelectedTab, trans);
574 }
575 mSelectedTab = (TabImpl) tab;
576 if (mSelectedTab != null) {
577 mSelectedTab.getCallback().onTabSelected(mSelectedTab, trans);
578 }
Adam Powell2b6230e2010-09-07 17:55:25 -0700579 }
580
581 if (!trans.isEmpty()) {
582 trans.commit();
583 }
584 }
585
586 @Override
587 public Tab getSelectedTab() {
588 return mSelectedTab;
Adam Powell661c9082010-07-02 10:09:44 -0700589 }
590
Adam Powell6b336f82010-08-10 20:13:01 -0700591 @Override
592 public int getHeight() {
Adam Powell58c5dc12011-07-14 21:08:10 -0700593 return mContainerView.getHeight();
Adam Powell6b336f82010-08-10 20:13:01 -0700594 }
595
Dianne Hackborndf7221c2013-02-26 14:53:55 -0800596 public void enableContentAnimations(boolean enabled) {
597 mContentAnimations = enabled;
598 }
599
Adam Powell6b336f82010-08-10 20:13:01 -0700600 @Override
601 public void show() {
Dianne Hackborn139e5aa2012-05-05 20:36:38 -0700602 if (mHiddenByApp) {
603 mHiddenByApp = false;
604 updateVisibility(false);
605 }
Adam Powell07e1f982011-03-24 11:11:15 -0700606 }
607
Dianne Hackborn139e5aa2012-05-05 20:36:38 -0700608 private void showForActionMode() {
609 if (!mShowingForMode) {
610 mShowingForMode = true;
611 if (mOverlayLayout != null) {
612 mOverlayLayout.setShowingForActionMode(true);
613 }
614 updateVisibility(false);
615 }
616 }
617
618 public void showForSystem() {
619 if (mHiddenBySystem) {
620 mHiddenBySystem = false;
621 updateVisibility(true);
622 }
623 }
624
625 @Override
626 public void hide() {
627 if (!mHiddenByApp) {
628 mHiddenByApp = true;
629 updateVisibility(false);
630 }
631 }
632
633 private void hideForActionMode() {
634 if (mShowingForMode) {
635 mShowingForMode = false;
636 if (mOverlayLayout != null) {
637 mOverlayLayout.setShowingForActionMode(false);
638 }
639 updateVisibility(false);
640 }
641 }
642
643 public void hideForSystem() {
644 if (!mHiddenBySystem) {
645 mHiddenBySystem = true;
646 updateVisibility(true);
647 }
648 }
649
650 private static boolean checkShowingFlags(boolean hiddenByApp, boolean hiddenBySystem,
651 boolean showingForMode) {
652 if (showingForMode) {
653 return true;
654 } else if (hiddenByApp || hiddenBySystem) {
655 return false;
656 } else {
657 return true;
658 }
659 }
660
661 private void updateVisibility(boolean fromSystem) {
662 // Based on the current state, should we be hidden or shown?
663 final boolean shown = checkShowingFlags(mHiddenByApp, mHiddenBySystem,
664 mShowingForMode);
665
666 if (shown) {
667 if (!mNowShowing) {
668 mNowShowing = true;
669 doShow(fromSystem);
670 }
671 } else {
672 if (mNowShowing) {
673 mNowShowing = false;
674 doHide(fromSystem);
675 }
676 }
677 }
678
679 public void doShow(boolean fromSystem) {
Adam Powell07e1f982011-03-24 11:11:15 -0700680 if (mCurrentShowAnim != null) {
681 mCurrentShowAnim.end();
Adam Powell45f1e082010-12-10 14:20:13 -0800682 }
Adam Powell9b0dc282013-07-31 13:58:43 -0700683 mContainerView.setVisibility(View.VISIBLE);
Adam Powell50efbed2011-02-08 16:20:15 -0800684
Dianne Hackborn3a3a6cf2012-03-26 10:24:04 -0700685 if (mCurWindowVisibility == View.VISIBLE && (mShowHideAnimationEnabled
Dianne Hackborn139e5aa2012-05-05 20:36:38 -0700686 || fromSystem)) {
Adam Powell9b0dc282013-07-31 13:58:43 -0700687 mContainerView.setTranslationY(0); // because we're about to ask its window loc
688 float startingY = -mContainerView.getHeight();
Chet Haasee8118e12012-05-30 14:19:02 -0700689 if (fromSystem) {
690 int topLeft[] = {0, 0};
Adam Powell9b0dc282013-07-31 13:58:43 -0700691 mContainerView.getLocationInWindow(topLeft);
Chet Haasee8118e12012-05-30 14:19:02 -0700692 startingY -= topLeft[1];
693 }
Adam Powell9b0dc282013-07-31 13:58:43 -0700694 mContainerView.setTranslationY(startingY);
Adam Powell50efbed2011-02-08 16:20:15 -0800695 AnimatorSet anim = new AnimatorSet();
Adam Powell9b0dc282013-07-31 13:58:43 -0700696 ObjectAnimator a = ObjectAnimator.ofFloat(mContainerView, View.TRANSLATION_Y, 0);
697 a.addUpdateListener(mUpdateListener);
698 AnimatorSet.Builder b = anim.play(a);
Dianne Hackborndf7221c2013-02-26 14:53:55 -0800699 if (mContentAnimations && mContentView != null) {
Adam Powell9b0dc282013-07-31 13:58:43 -0700700 b.with(ObjectAnimator.ofFloat(mContentView, View.TRANSLATION_Y,
Chet Haasee8118e12012-05-30 14:19:02 -0700701 startingY, 0));
Adam Powell50efbed2011-02-08 16:20:15 -0800702 }
Adam Powell1ab418a2011-06-09 20:49:49 -0700703 if (mSplitView != null && mContextDisplayMode == CONTEXT_DISPLAY_SPLIT) {
Dianne Hackborn8eedb8b2012-04-16 19:31:58 -0700704 mSplitView.setTranslationY(mSplitView.getHeight());
Adam Powell993a63a2011-08-18 16:35:53 -0700705 mSplitView.setVisibility(View.VISIBLE);
Adam Powell9b0dc282013-07-31 13:58:43 -0700706 b.with(ObjectAnimator.ofFloat(mSplitView, View.TRANSLATION_Y, 0));
Adam Powell640a66e2011-04-29 10:18:53 -0700707 }
Dianne Hackborn8eedb8b2012-04-16 19:31:58 -0700708 anim.setInterpolator(AnimationUtils.loadInterpolator(mContext,
Chet Haasee8118e12012-05-30 14:19:02 -0700709 com.android.internal.R.interpolator.decelerate_cubic));
710 anim.setDuration(250);
Dianne Hackborn139e5aa2012-05-05 20:36:38 -0700711 // If this is being shown from the system, add a small delay.
712 // This is because we will also be animating in the status bar,
713 // and these two elements can't be done in lock-step. So we give
714 // a little time for the status bar to start its animation before
715 // the action bar animates. (This corresponds to the corresponding
716 // case when hiding, where the status bar has a small delay before
717 // starting.)
Adam Powell50efbed2011-02-08 16:20:15 -0800718 anim.addListener(mShowListener);
Adam Powell07e1f982011-03-24 11:11:15 -0700719 mCurrentShowAnim = anim;
Adam Powell50efbed2011-02-08 16:20:15 -0800720 anim.start();
721 } else {
Adam Powell9b0dc282013-07-31 13:58:43 -0700722 mContainerView.setAlpha(1);
723 mContainerView.setTranslationY(0);
Dianne Hackborndf7221c2013-02-26 14:53:55 -0800724 if (mContentAnimations && mContentView != null) {
Dianne Hackborn80d55062012-05-22 18:03:20 -0700725 mContentView.setTranslationY(0);
726 }
727 if (mSplitView != null && mContextDisplayMode == CONTEXT_DISPLAY_SPLIT) {
728 mSplitView.setAlpha(1);
729 mSplitView.setTranslationY(0);
730 mSplitView.setVisibility(View.VISIBLE);
731 }
Adam Powell50efbed2011-02-08 16:20:15 -0800732 mShowListener.onAnimationEnd(null);
Adam Powelle6ec7322010-12-07 15:29:26 -0800733 }
Dianne Hackborn139e5aa2012-05-05 20:36:38 -0700734 if (mOverlayLayout != null) {
735 mOverlayLayout.requestFitSystemWindows();
736 }
Adam Powell6b336f82010-08-10 20:13:01 -0700737 }
738
Dianne Hackborn139e5aa2012-05-05 20:36:38 -0700739 public void doHide(boolean fromSystem) {
Adam Powell07e1f982011-03-24 11:11:15 -0700740 if (mCurrentShowAnim != null) {
741 mCurrentShowAnim.end();
Adam Powelle6ec7322010-12-07 15:29:26 -0800742 }
Adam Powell50efbed2011-02-08 16:20:15 -0800743
Dianne Hackborn3a3a6cf2012-03-26 10:24:04 -0700744 if (mCurWindowVisibility == View.VISIBLE && (mShowHideAnimationEnabled
Dianne Hackborn139e5aa2012-05-05 20:36:38 -0700745 || fromSystem)) {
Adam Powell9b0dc282013-07-31 13:58:43 -0700746 mContainerView.setAlpha(1);
Adam Powell01feaee2011-02-10 15:05:05 -0800747 mContainerView.setTransitioning(true);
Adam Powell50efbed2011-02-08 16:20:15 -0800748 AnimatorSet anim = new AnimatorSet();
Adam Powell9b0dc282013-07-31 13:58:43 -0700749 float endingY = -mContainerView.getHeight();
Chet Haasee8118e12012-05-30 14:19:02 -0700750 if (fromSystem) {
751 int topLeft[] = {0, 0};
Adam Powell9b0dc282013-07-31 13:58:43 -0700752 mContainerView.getLocationInWindow(topLeft);
Chet Haasee8118e12012-05-30 14:19:02 -0700753 endingY -= topLeft[1];
754 }
Adam Powell9b0dc282013-07-31 13:58:43 -0700755 ObjectAnimator a = ObjectAnimator.ofFloat(mContainerView, View.TRANSLATION_Y, endingY);
756 a.addUpdateListener(mUpdateListener);
757 AnimatorSet.Builder b = anim.play(a);
Dianne Hackborndf7221c2013-02-26 14:53:55 -0800758 if (mContentAnimations && mContentView != null) {
Adam Powell9b0dc282013-07-31 13:58:43 -0700759 b.with(ObjectAnimator.ofFloat(mContentView, View.TRANSLATION_Y,
Chet Haasee8118e12012-05-30 14:19:02 -0700760 0, endingY));
Adam Powell50efbed2011-02-08 16:20:15 -0800761 }
Adam Powell1ab418a2011-06-09 20:49:49 -0700762 if (mSplitView != null && mSplitView.getVisibility() == View.VISIBLE) {
Adam Powell640a66e2011-04-29 10:18:53 -0700763 mSplitView.setAlpha(1);
Adam Powell9b0dc282013-07-31 13:58:43 -0700764 b.with(ObjectAnimator.ofFloat(mSplitView, View.TRANSLATION_Y,
Dianne Hackborn8eedb8b2012-04-16 19:31:58 -0700765 mSplitView.getHeight()));
Adam Powell640a66e2011-04-29 10:18:53 -0700766 }
Dianne Hackborn8eedb8b2012-04-16 19:31:58 -0700767 anim.setInterpolator(AnimationUtils.loadInterpolator(mContext,
Chet Haasee8118e12012-05-30 14:19:02 -0700768 com.android.internal.R.interpolator.accelerate_cubic));
769 anim.setDuration(250);
Adam Powell50efbed2011-02-08 16:20:15 -0800770 anim.addListener(mHideListener);
Adam Powell07e1f982011-03-24 11:11:15 -0700771 mCurrentShowAnim = anim;
Adam Powell50efbed2011-02-08 16:20:15 -0800772 anim.start();
773 } else {
774 mHideListener.onAnimationEnd(null);
Adam Powelle6ec7322010-12-07 15:29:26 -0800775 }
Adam Powell6b336f82010-08-10 20:13:01 -0700776 }
777
778 public boolean isShowing() {
Dianne Hackborn139e5aa2012-05-05 20:36:38 -0700779 return mNowShowing;
780 }
781
782 public boolean isSystemShowing() {
783 return !mHiddenBySystem;
Adam Powelld8b3f2e2010-12-02 13:37:03 -0800784 }
785
Adam Powell640a66e2011-04-29 10:18:53 -0700786 void animateToMode(boolean toActionMode) {
Adam Powell060e3ca2011-07-19 20:39:16 -0700787 if (toActionMode) {
Dianne Hackborn139e5aa2012-05-05 20:36:38 -0700788 showForActionMode();
789 } else {
790 hideForActionMode();
Adam Powell07e1f982011-03-24 11:11:15 -0700791 }
Adam Powelld8b3f2e2010-12-02 13:37:03 -0800792
Adam Powell640a66e2011-04-29 10:18:53 -0700793 mActionView.animateToVisibility(toActionMode ? View.GONE : View.VISIBLE);
794 mContextView.animateToVisibility(toActionMode ? View.VISIBLE : View.GONE);
Adam Powellf6ce6a92011-06-29 10:25:01 -0700795 if (mTabScrollView != null && !mActionView.hasEmbeddedTabs() && mActionView.isCollapsed()) {
796 mTabScrollView.animateToVisibility(toActionMode ? View.GONE : View.VISIBLE);
797 }
Adam Powell6b336f82010-08-10 20:13:01 -0700798 }
799
Adam Powell88ab6972011-07-28 11:25:01 -0700800 public Context getThemedContext() {
801 if (mThemedContext == null) {
802 TypedValue outValue = new TypedValue();
803 Resources.Theme currentTheme = mContext.getTheme();
804 currentTheme.resolveAttribute(com.android.internal.R.attr.actionBarWidgetTheme,
805 outValue, true);
806 final int targetThemeRes = outValue.resourceId;
807
808 if (targetThemeRes != 0 && mContext.getThemeResId() != targetThemeRes) {
809 mThemedContext = new ContextThemeWrapper(mContext, targetThemeRes);
810 } else {
811 mThemedContext = mContext;
812 }
813 }
814 return mThemedContext;
815 }
816
Adam Powell27cba382013-01-22 18:55:20 -0800817 @Override
818 public boolean isTitleTruncated() {
819 return mActionView != null && mActionView.isTitleTruncated();
820 }
821
Adam Powelle0e2f4f2013-04-05 16:27:35 -0700822 @Override
823 public void setHomeAsUpIndicator(Drawable indicator) {
824 mActionView.setHomeAsUpIndicator(indicator);
825 }
826
827 @Override
828 public void setHomeAsUpIndicator(int resId) {
829 mActionView.setHomeAsUpIndicator(resId);
830 }
831
832 @Override
833 public void setHomeActionContentDescription(CharSequence description) {
834 mActionView.setHomeActionContentDescription(description);
835 }
836
837 @Override
838 public void setHomeActionContentDescription(int resId) {
839 mActionView.setHomeActionContentDescription(resId);
840 }
841
Adam Powell89e06452010-06-23 20:24:52 -0700842 /**
843 * @hide
844 */
Adam Powell5d279772010-07-27 16:34:07 -0700845 public class ActionModeImpl extends ActionMode implements MenuBuilder.Callback {
Adam Powell6e346362010-07-23 10:18:23 -0700846 private ActionMode.Callback mCallback;
Adam Powell2c9c9fe2010-07-16 10:17:57 -0700847 private MenuBuilder mMenu;
Adam Powell29ed7572010-07-14 16:24:56 -0700848 private WeakReference<View> mCustomView;
Adam Powell89e06452010-06-23 20:24:52 -0700849
Adam Powell5d279772010-07-27 16:34:07 -0700850 public ActionModeImpl(ActionMode.Callback callback) {
Adam Powell89e06452010-06-23 20:24:52 -0700851 mCallback = callback;
Adam Powellf2423682011-08-11 14:29:45 -0700852 mMenu = new MenuBuilder(getThemedContext())
Adam Powell4d9861e2010-08-17 11:14:40 -0700853 .setDefaultShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM);
Adam Powell2c9c9fe2010-07-16 10:17:57 -0700854 mMenu.setCallback(this);
Adam Powell89e06452010-06-23 20:24:52 -0700855 }
Adam Powell9168f0b2010-08-02 15:46:24 -0700856
857 @Override
858 public MenuInflater getMenuInflater() {
Adam Powellf2423682011-08-11 14:29:45 -0700859 return new MenuInflater(getThemedContext());
Adam Powell9168f0b2010-08-02 15:46:24 -0700860 }
861
Adam Powell89e06452010-06-23 20:24:52 -0700862 @Override
863 public Menu getMenu() {
864 return mMenu;
865 }
866
867 @Override
868 public void finish() {
Adam Powell5d279772010-07-27 16:34:07 -0700869 if (mActionMode != this) {
870 // Not the active action mode - no-op
Adam Powell93b6bc32010-07-22 11:36:35 -0700871 return;
872 }
873
Dianne Hackborn139e5aa2012-05-05 20:36:38 -0700874 // If this change in state is going to cause the action bar
875 // to be hidden, defer the onDestroy callback until the animation
876 // is finished and associated relayout is about to happen. This lets
877 // apps better anticipate visibility and layout behavior.
878 if (!checkShowingFlags(mHiddenByApp, mHiddenBySystem, false)) {
879 // With the current state but the action bar hidden, our
880 // overall showing state is going to be false.
Adam Powell060e3ca2011-07-19 20:39:16 -0700881 mDeferredDestroyActionMode = this;
882 mDeferredModeDestroyCallback = mCallback;
883 } else {
884 mCallback.onDestroyActionMode(this);
885 }
Adam Powelld8b3f2e2010-12-02 13:37:03 -0800886 mCallback = null;
Adam Powell640a66e2011-04-29 10:18:53 -0700887 animateToMode(false);
Adam Powell0e94b512010-06-29 17:58:20 -0700888
889 // Clear out the context mode views after the animation finishes
Adam Powell640a66e2011-04-29 10:18:53 -0700890 mContextView.closeMode();
Adam Powell86ed4362011-09-14 16:18:53 -0700891 mActionView.sendAccessibilityEvent(AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED);
Adam Powellf6ce6a92011-06-29 10:25:01 -0700892
Adam Powell5d279772010-07-27 16:34:07 -0700893 mActionMode = null;
Adam Powell89e06452010-06-23 20:24:52 -0700894 }
895
896 @Override
897 public void invalidate() {
Adam Powell5ee36c42011-06-02 12:59:43 -0700898 mMenu.stopDispatchingItemsChanged();
899 try {
900 mCallback.onPrepareActionMode(this, mMenu);
901 } finally {
902 mMenu.startDispatchingItemsChanged();
903 }
904 }
905
906 public boolean dispatchOnCreate() {
907 mMenu.stopDispatchingItemsChanged();
908 try {
909 return mCallback.onCreateActionMode(this, mMenu);
910 } finally {
911 mMenu.startDispatchingItemsChanged();
Adam Powell89e06452010-06-23 20:24:52 -0700912 }
913 }
914
915 @Override
916 public void setCustomView(View view) {
Adam Powell640a66e2011-04-29 10:18:53 -0700917 mContextView.setCustomView(view);
Adam Powell29ed7572010-07-14 16:24:56 -0700918 mCustomView = new WeakReference<View>(view);
Adam Powell89e06452010-06-23 20:24:52 -0700919 }
920
921 @Override
922 public void setSubtitle(CharSequence subtitle) {
Adam Powell640a66e2011-04-29 10:18:53 -0700923 mContextView.setSubtitle(subtitle);
Adam Powell89e06452010-06-23 20:24:52 -0700924 }
925
926 @Override
927 public void setTitle(CharSequence title) {
Adam Powell640a66e2011-04-29 10:18:53 -0700928 mContextView.setTitle(title);
Adam Powell89e06452010-06-23 20:24:52 -0700929 }
Adam Powell29ed7572010-07-14 16:24:56 -0700930
931 @Override
Adam Powellc9ae2a22010-07-28 14:44:21 -0700932 public void setTitle(int resId) {
Adam Powell48e8ac32011-01-14 12:10:24 -0800933 setTitle(mContext.getResources().getString(resId));
Adam Powellc9ae2a22010-07-28 14:44:21 -0700934 }
935
936 @Override
937 public void setSubtitle(int resId) {
Adam Powell48e8ac32011-01-14 12:10:24 -0800938 setSubtitle(mContext.getResources().getString(resId));
Adam Powellc9ae2a22010-07-28 14:44:21 -0700939 }
940
941 @Override
Adam Powell29ed7572010-07-14 16:24:56 -0700942 public CharSequence getTitle() {
Adam Powell640a66e2011-04-29 10:18:53 -0700943 return mContextView.getTitle();
Adam Powell29ed7572010-07-14 16:24:56 -0700944 }
945
946 @Override
947 public CharSequence getSubtitle() {
Adam Powell640a66e2011-04-29 10:18:53 -0700948 return mContextView.getSubtitle();
Adam Powell29ed7572010-07-14 16:24:56 -0700949 }
Adam Powell89e06452010-06-23 20:24:52 -0700950
Adam Powell29ed7572010-07-14 16:24:56 -0700951 @Override
Adam Powellb98a81f2012-02-24 11:09:07 -0800952 public void setTitleOptionalHint(boolean titleOptional) {
Adam Powell785c4472012-05-02 21:25:39 -0700953 super.setTitleOptionalHint(titleOptional);
Adam Powellb98a81f2012-02-24 11:09:07 -0800954 mContextView.setTitleOptional(titleOptional);
955 }
956
957 @Override
958 public boolean isTitleOptional() {
959 return mContextView.isTitleOptional();
960 }
961
962 @Override
Adam Powell29ed7572010-07-14 16:24:56 -0700963 public View getCustomView() {
964 return mCustomView != null ? mCustomView.get() : null;
965 }
966
Adam Powell2c9c9fe2010-07-16 10:17:57 -0700967 public boolean onMenuItemSelected(MenuBuilder menu, MenuItem item) {
Adam Powelld8b3f2e2010-12-02 13:37:03 -0800968 if (mCallback != null) {
969 return mCallback.onActionItemClicked(this, item);
970 } else {
971 return false;
972 }
Adam Powell2c9c9fe2010-07-16 10:17:57 -0700973 }
974
975 public void onCloseMenu(MenuBuilder menu, boolean allMenusAreClosing) {
976 }
977
978 public boolean onSubMenuSelected(SubMenuBuilder subMenu) {
Adam Powelld8b3f2e2010-12-02 13:37:03 -0800979 if (mCallback == null) {
980 return false;
981 }
982
Adam Powell2c9c9fe2010-07-16 10:17:57 -0700983 if (!subMenu.hasVisibleItems()) {
984 return true;
Adam Powell89e06452010-06-23 20:24:52 -0700985 }
Adam Powell2c9c9fe2010-07-16 10:17:57 -0700986
Adam Powellf2423682011-08-11 14:29:45 -0700987 new MenuPopupHelper(getThemedContext(), subMenu).show();
Adam Powell2c9c9fe2010-07-16 10:17:57 -0700988 return true;
989 }
990
991 public void onCloseSubMenu(SubMenuBuilder menu) {
992 }
993
994 public void onMenuModeChange(MenuBuilder menu) {
Adam Powelld8b3f2e2010-12-02 13:37:03 -0800995 if (mCallback == null) {
996 return;
997 }
Adam Powellf6148c52010-08-11 21:10:16 -0700998 invalidate();
Adam Powell640a66e2011-04-29 10:18:53 -0700999 mContextView.showOverflowMenu();
Adam Powell2c9c9fe2010-07-16 10:17:57 -07001000 }
Adam Powell661c9082010-07-02 10:09:44 -07001001 }
1002
1003 /**
1004 * @hide
1005 */
1006 public class TabImpl extends ActionBar.Tab {
Adam Powell2b6230e2010-09-07 17:55:25 -07001007 private ActionBar.TabListener mCallback;
1008 private Object mTag;
Adam Powell661c9082010-07-02 10:09:44 -07001009 private Drawable mIcon;
1010 private CharSequence mText;
Adam Powell94e56ef2011-09-06 21:22:22 -07001011 private CharSequence mContentDesc;
Adam Powell0d8ec1d2011-05-03 14:49:13 -07001012 private int mPosition = -1;
Adam Powell2b6230e2010-09-07 17:55:25 -07001013 private View mCustomView;
Adam Powell661c9082010-07-02 10:09:44 -07001014
1015 @Override
Adam Powell2b6230e2010-09-07 17:55:25 -07001016 public Object getTag() {
1017 return mTag;
1018 }
1019
1020 @Override
Adam Powell9ab97872010-10-26 21:47:29 -07001021 public Tab setTag(Object tag) {
Adam Powell2b6230e2010-09-07 17:55:25 -07001022 mTag = tag;
Adam Powell9ab97872010-10-26 21:47:29 -07001023 return this;
Adam Powell2b6230e2010-09-07 17:55:25 -07001024 }
1025
1026 public ActionBar.TabListener getCallback() {
1027 return mCallback;
1028 }
1029
1030 @Override
Adam Powell9ab97872010-10-26 21:47:29 -07001031 public Tab setTabListener(ActionBar.TabListener callback) {
Adam Powell2b6230e2010-09-07 17:55:25 -07001032 mCallback = callback;
Adam Powell9ab97872010-10-26 21:47:29 -07001033 return this;
Adam Powell2b6230e2010-09-07 17:55:25 -07001034 }
1035
1036 @Override
1037 public View getCustomView() {
1038 return mCustomView;
1039 }
1040
1041 @Override
Adam Powell9ab97872010-10-26 21:47:29 -07001042 public Tab setCustomView(View view) {
Adam Powell2b6230e2010-09-07 17:55:25 -07001043 mCustomView = view;
Adam Powellf8ac6b72011-05-23 18:14:09 -07001044 if (mPosition >= 0) {
1045 mTabScrollView.updateTab(mPosition);
1046 }
Adam Powell9ab97872010-10-26 21:47:29 -07001047 return this;
Adam Powell661c9082010-07-02 10:09:44 -07001048 }
1049
1050 @Override
Adam Powell32555f32010-11-17 13:49:22 -08001051 public Tab setCustomView(int layoutResId) {
Adam Powellf2423682011-08-11 14:29:45 -07001052 return setCustomView(LayoutInflater.from(getThemedContext())
1053 .inflate(layoutResId, null));
Adam Powell32555f32010-11-17 13:49:22 -08001054 }
1055
1056 @Override
Adam Powell661c9082010-07-02 10:09:44 -07001057 public Drawable getIcon() {
1058 return mIcon;
1059 }
1060
1061 @Override
1062 public int getPosition() {
1063 return mPosition;
1064 }
1065
1066 public void setPosition(int position) {
1067 mPosition = position;
1068 }
1069
1070 @Override
1071 public CharSequence getText() {
1072 return mText;
1073 }
1074
1075 @Override
Adam Powell9ab97872010-10-26 21:47:29 -07001076 public Tab setIcon(Drawable icon) {
Adam Powell661c9082010-07-02 10:09:44 -07001077 mIcon = icon;
Adam Powellf8ac6b72011-05-23 18:14:09 -07001078 if (mPosition >= 0) {
1079 mTabScrollView.updateTab(mPosition);
1080 }
Adam Powell9ab97872010-10-26 21:47:29 -07001081 return this;
Adam Powell661c9082010-07-02 10:09:44 -07001082 }
1083
1084 @Override
Adam Powell32555f32010-11-17 13:49:22 -08001085 public Tab setIcon(int resId) {
Alan Viverette8eea3ea2014-02-03 18:40:20 -08001086 return setIcon(mContext.getDrawable(resId));
Adam Powell32555f32010-11-17 13:49:22 -08001087 }
1088
1089 @Override
Adam Powell9ab97872010-10-26 21:47:29 -07001090 public Tab setText(CharSequence text) {
Adam Powell661c9082010-07-02 10:09:44 -07001091 mText = text;
Adam Powellf8ac6b72011-05-23 18:14:09 -07001092 if (mPosition >= 0) {
1093 mTabScrollView.updateTab(mPosition);
1094 }
Adam Powell9ab97872010-10-26 21:47:29 -07001095 return this;
Adam Powell661c9082010-07-02 10:09:44 -07001096 }
1097
1098 @Override
Adam Powell32555f32010-11-17 13:49:22 -08001099 public Tab setText(int resId) {
1100 return setText(mContext.getResources().getText(resId));
1101 }
1102
1103 @Override
Adam Powell661c9082010-07-02 10:09:44 -07001104 public void select() {
1105 selectTab(this);
Adam Powell89e06452010-06-23 20:24:52 -07001106 }
Adam Powell94e56ef2011-09-06 21:22:22 -07001107
1108 @Override
1109 public Tab setContentDescription(int resId) {
1110 return setContentDescription(mContext.getResources().getText(resId));
1111 }
1112
1113 @Override
1114 public Tab setContentDescription(CharSequence contentDesc) {
1115 mContentDesc = contentDesc;
1116 if (mPosition >= 0) {
1117 mTabScrollView.updateTab(mPosition);
1118 }
1119 return this;
1120 }
1121
1122 @Override
1123 public CharSequence getContentDescription() {
1124 return mContentDesc;
1125 }
Adam Powell89e06452010-06-23 20:24:52 -07001126 }
Adam Powell9ab97872010-10-26 21:47:29 -07001127
1128 @Override
1129 public void setCustomView(View view) {
1130 mActionView.setCustomNavigationView(view);
1131 }
1132
1133 @Override
1134 public void setCustomView(View view, LayoutParams layoutParams) {
1135 view.setLayoutParams(layoutParams);
1136 mActionView.setCustomNavigationView(view);
1137 }
1138
1139 @Override
Adam Powell8515ee82010-11-30 14:09:55 -08001140 public void setListNavigationCallbacks(SpinnerAdapter adapter, OnNavigationListener callback) {
Adam Powell9ab97872010-10-26 21:47:29 -07001141 mActionView.setDropdownAdapter(adapter);
1142 mActionView.setCallback(callback);
1143 }
1144
1145 @Override
1146 public int getSelectedNavigationIndex() {
1147 switch (mActionView.getNavigationMode()) {
1148 case NAVIGATION_MODE_TABS:
Adam Powell04587962010-11-11 22:15:07 -08001149 return mSelectedTab != null ? mSelectedTab.getPosition() : -1;
Adam Powell9ab97872010-10-26 21:47:29 -07001150 case NAVIGATION_MODE_LIST:
1151 return mActionView.getDropdownSelectedPosition();
1152 default:
1153 return -1;
1154 }
1155 }
1156
1157 @Override
1158 public int getNavigationItemCount() {
1159 switch (mActionView.getNavigationMode()) {
1160 case NAVIGATION_MODE_TABS:
1161 return mTabs.size();
1162 case NAVIGATION_MODE_LIST:
1163 SpinnerAdapter adapter = mActionView.getDropdownAdapter();
1164 return adapter != null ? adapter.getCount() : 0;
1165 default:
1166 return 0;
1167 }
1168 }
1169
1170 @Override
Adam Powell0c24a552010-11-03 16:44:11 -07001171 public int getTabCount() {
1172 return mTabs.size();
1173 }
1174
1175 @Override
Adam Powell9ab97872010-10-26 21:47:29 -07001176 public void setNavigationMode(int mode) {
Adam Powell0c24a552010-11-03 16:44:11 -07001177 final int oldMode = mActionView.getNavigationMode();
1178 switch (oldMode) {
1179 case NAVIGATION_MODE_TABS:
1180 mSavedTabPosition = getSelectedNavigationIndex();
1181 selectTab(null);
Adam Powellf5645cb2011-08-10 22:49:02 -07001182 mTabScrollView.setVisibility(View.GONE);
Adam Powell0c24a552010-11-03 16:44:11 -07001183 break;
1184 }
Dianne Hackborn3a3a6cf2012-03-26 10:24:04 -07001185 if (oldMode != mode && !mHasEmbeddedTabs) {
1186 if (mOverlayLayout != null) {
1187 mOverlayLayout.requestFitSystemWindows();
1188 }
1189 }
Adam Powell9ab97872010-10-26 21:47:29 -07001190 mActionView.setNavigationMode(mode);
Adam Powell0c24a552010-11-03 16:44:11 -07001191 switch (mode) {
1192 case NAVIGATION_MODE_TABS:
Adam Powellf8ac6b72011-05-23 18:14:09 -07001193 ensureTabsExist();
Adam Powellf5645cb2011-08-10 22:49:02 -07001194 mTabScrollView.setVisibility(View.VISIBLE);
Adam Powell0c24a552010-11-03 16:44:11 -07001195 if (mSavedTabPosition != INVALID_POSITION) {
1196 setSelectedNavigationItem(mSavedTabPosition);
1197 mSavedTabPosition = INVALID_POSITION;
1198 }
1199 break;
1200 }
Adam Powelld21aa122011-05-27 13:09:52 -07001201 mActionView.setCollapsable(mode == NAVIGATION_MODE_TABS && !mHasEmbeddedTabs);
Adam Powell9ab97872010-10-26 21:47:29 -07001202 }
1203
1204 @Override
1205 public Tab getTabAt(int index) {
1206 return mTabs.get(index);
1207 }
Adam Powell0c24a552010-11-03 16:44:11 -07001208
Adam Powell0c24a552010-11-03 16:44:11 -07001209
Adam Powell1969b872011-03-22 11:52:48 -07001210 @Override
1211 public void setIcon(int resId) {
Adam Powell45c515b2011-04-21 18:50:20 -07001212 mActionView.setIcon(resId);
Adam Powell1969b872011-03-22 11:52:48 -07001213 }
Adam Powell0c24a552010-11-03 16:44:11 -07001214
Adam Powell1969b872011-03-22 11:52:48 -07001215 @Override
1216 public void setIcon(Drawable icon) {
1217 mActionView.setIcon(icon);
1218 }
1219
Adam Powell04fe6eb2013-05-31 14:39:48 -07001220 public boolean hasIcon() {
1221 return mActionView.hasIcon();
1222 }
1223
Adam Powell1969b872011-03-22 11:52:48 -07001224 @Override
1225 public void setLogo(int resId) {
Adam Powell45c515b2011-04-21 18:50:20 -07001226 mActionView.setLogo(resId);
Adam Powell1969b872011-03-22 11:52:48 -07001227 }
1228
1229 @Override
1230 public void setLogo(Drawable logo) {
1231 mActionView.setLogo(logo);
Adam Powell0c24a552010-11-03 16:44:11 -07001232 }
Adam Powelldd8fab22012-03-22 17:47:27 -07001233
Adam Powell04fe6eb2013-05-31 14:39:48 -07001234 public boolean hasLogo() {
1235 return mActionView.hasLogo();
1236 }
1237
Adam Powelldd8fab22012-03-22 17:47:27 -07001238 public void setDefaultDisplayHomeAsUpEnabled(boolean enable) {
1239 if (!mDisplayHomeAsUpSet) {
1240 setDisplayHomeAsUpEnabled(enable);
1241 }
1242 }
Adam Powell89e06452010-06-23 20:24:52 -07001243}