blob: 066d6c302b17aeb5f9190924790021e0b6cc0c09 [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;
Dianne Hackborn139e5aa2012-05-05 20:36:38 -070045import android.util.Log;
Adam Powell88ab6972011-07-28 11:25:01 -070046import android.util.TypedValue;
Adam Powell6e346362010-07-23 10:18:23 -070047import android.view.ActionMode;
Adam Powell88ab6972011-07-28 11:25:01 -070048import android.view.ContextThemeWrapper;
Adam Powell32555f32010-11-17 13:49:22 -080049import android.view.LayoutInflater;
Adam Powell89e06452010-06-23 20:24:52 -070050import android.view.Menu;
Adam Powell9168f0b2010-08-02 15:46:24 -070051import android.view.MenuInflater;
Adam Powell89e06452010-06-23 20:24:52 -070052import android.view.MenuItem;
53import android.view.View;
Dianne Hackborn3a3a6cf2012-03-26 10:24:04 -070054import android.view.ViewGroup;
Adam Powelle6ec7322010-12-07 15:29:26 -080055import android.view.Window;
Adam Powell86ed4362011-09-14 16:18:53 -070056import android.view.accessibility.AccessibilityEvent;
Dianne Hackborn8eedb8b2012-04-16 19:31:58 -070057import android.view.animation.AnimationUtils;
Adam Powell89e06452010-06-23 20:24:52 -070058import android.widget.SpinnerAdapter;
Adam Powell89e06452010-06-23 20:24:52 -070059
Adam Powell29ed7572010-07-14 16:24:56 -070060import java.lang.ref.WeakReference;
Adam Powell661c9082010-07-02 10:09:44 -070061import java.util.ArrayList;
62
Adam Powell89e06452010-06-23 20:24:52 -070063/**
64 * ActionBarImpl is the ActionBar implementation used
65 * by devices of all screen sizes. If it detects a compatible decor,
66 * it will split contextual modes across both the ActionBarView at
67 * the top of the screen and a horizontal LinearLayout at the bottom
68 * which is normally hidden.
69 */
70public class ActionBarImpl extends ActionBar {
Adam Powelld8145042011-03-24 14:18:27 -070071 private static final String TAG = "ActionBarImpl";
Adam Powell661c9082010-07-02 10:09:44 -070072
Adam Powelldec9dfd2010-08-09 15:27:54 -070073 private Context mContext;
Adam Powell88ab6972011-07-28 11:25:01 -070074 private Context mThemedContext;
Adam Powell661c9082010-07-02 10:09:44 -070075 private Activity mActivity;
Adam Powelldec9dfd2010-08-09 15:27:54 -070076 private Dialog mDialog;
Adam Powell661c9082010-07-02 10:09:44 -070077
Dianne Hackborn3a3a6cf2012-03-26 10:24:04 -070078 private ActionBarOverlayLayout mOverlayLayout;
Adam Powell01feaee2011-02-10 15:05:05 -080079 private ActionBarContainer mContainerView;
Adam Powell89e06452010-06-23 20:24:52 -070080 private ActionBarView mActionView;
Adam Powell640a66e2011-04-29 10:18:53 -070081 private ActionBarContextView mContextView;
82 private ActionBarContainer mSplitView;
Adam Powelle6ec7322010-12-07 15:29:26 -080083 private View mContentView;
Adam Powellf8ac6b72011-05-23 18:14:09 -070084 private ScrollingTabContainerView mTabScrollView;
Adam Powell661c9082010-07-02 10:09:44 -070085
86 private ArrayList<TabImpl> mTabs = new ArrayList<TabImpl>();
87
Adam Powell661c9082010-07-02 10:09:44 -070088 private TabImpl mSelectedTab;
Adam Powell0c24a552010-11-03 16:44:11 -070089 private int mSavedTabPosition = INVALID_POSITION;
Adam Powell89e06452010-06-23 20:24:52 -070090
Adam Powelldd8fab22012-03-22 17:47:27 -070091 private boolean mDisplayHomeAsUpSet;
92
Adam Powell060e3ca2011-07-19 20:39:16 -070093 ActionModeImpl mActionMode;
94 ActionMode mDeferredDestroyActionMode;
95 ActionMode.Callback mDeferredModeDestroyCallback;
Adam Powell89e06452010-06-23 20:24:52 -070096
Adam Powell8515ee82010-11-30 14:09:55 -080097 private boolean mLastMenuVisibility;
98 private ArrayList<OnMenuVisibilityListener> mMenuVisibilityListeners =
99 new ArrayList<OnMenuVisibilityListener>();
100
Adam Powell89e06452010-06-23 20:24:52 -0700101 private static final int CONTEXT_DISPLAY_NORMAL = 0;
102 private static final int CONTEXT_DISPLAY_SPLIT = 1;
103
Adam Powell0c24a552010-11-03 16:44:11 -0700104 private static final int INVALID_POSITION = -1;
105
Adam Powell89e06452010-06-23 20:24:52 -0700106 private int mContextDisplayMode;
Adam Powellf8ac6b72011-05-23 18:14:09 -0700107 private boolean mHasEmbeddedTabs;
Adam Powell0e94b512010-06-29 17:58:20 -0700108
109 final Handler mHandler = new Handler();
Adam Powellf8ac6b72011-05-23 18:14:09 -0700110 Runnable mTabSelector;
Adam Powelld8b3f2e2010-12-02 13:37:03 -0800111
Dianne Hackborn3a3a6cf2012-03-26 10:24:04 -0700112 private int mCurWindowVisibility = View.VISIBLE;
113
Dianne Hackborndf7221c2013-02-26 14:53:55 -0800114 private boolean mContentAnimations = true;
Dianne Hackborn139e5aa2012-05-05 20:36:38 -0700115 private boolean mHiddenByApp;
116 private boolean mHiddenBySystem;
117 private boolean mShowingForMode;
118
119 private boolean mNowShowing = true;
120
Adam Powell07e1f982011-03-24 11:11:15 -0700121 private Animator mCurrentShowAnim;
Adam Powell50efbed2011-02-08 16:20:15 -0800122 private boolean mShowHideAnimationEnabled;
Adam Powelld8b3f2e2010-12-02 13:37:03 -0800123
Adam Powell07e1f982011-03-24 11:11:15 -0700124 final AnimatorListener mHideListener = new AnimatorListenerAdapter() {
Adam Powelle6ec7322010-12-07 15:29:26 -0800125 @Override
126 public void onAnimationEnd(Animator animation) {
Dianne Hackborndf7221c2013-02-26 14:53:55 -0800127 if (mContentAnimations && mContentView != null) {
Adam Powelle6ec7322010-12-07 15:29:26 -0800128 mContentView.setTranslationY(0);
Adam Powell9b0dc282013-07-31 13:58:43 -0700129 mContainerView.setTranslationY(0);
Adam Powelle6ec7322010-12-07 15:29:26 -0800130 }
Adam Powell993a63a2011-08-18 16:35:53 -0700131 if (mSplitView != null && mContextDisplayMode == CONTEXT_DISPLAY_SPLIT) {
132 mSplitView.setVisibility(View.GONE);
133 }
Adam Powell9b0dc282013-07-31 13:58:43 -0700134 mContainerView.setVisibility(View.GONE);
Adam Powell01feaee2011-02-10 15:05:05 -0800135 mContainerView.setTransitioning(false);
Adam Powell07e1f982011-03-24 11:11:15 -0700136 mCurrentShowAnim = null;
Adam Powell060e3ca2011-07-19 20:39:16 -0700137 completeDeferredDestroyActionMode();
Dianne Hackborn139e5aa2012-05-05 20:36:38 -0700138 if (mOverlayLayout != null) {
139 mOverlayLayout.requestFitSystemWindows();
140 }
Adam Powelle6ec7322010-12-07 15:29:26 -0800141 }
142 };
143
Adam Powell07e1f982011-03-24 11:11:15 -0700144 final AnimatorListener mShowListener = new AnimatorListenerAdapter() {
Adam Powelle6ec7322010-12-07 15:29:26 -0800145 @Override
146 public void onAnimationEnd(Animator animation) {
Adam Powell07e1f982011-03-24 11:11:15 -0700147 mCurrentShowAnim = null;
Adam Powell9b0dc282013-07-31 13:58:43 -0700148 mContainerView.requestLayout();
149 }
150 };
151
152 final ValueAnimator.AnimatorUpdateListener mUpdateListener =
153 new ValueAnimator.AnimatorUpdateListener() {
154 @Override
155 public void onAnimationUpdate(ValueAnimator animation) {
156 final ViewParent parent = mContainerView.getParent();
157 ((View) parent).invalidate();
Adam Powelle6ec7322010-12-07 15:29:26 -0800158 }
Adam Powelle6ec7322010-12-07 15:29:26 -0800159 };
160
Adam Powell661c9082010-07-02 10:09:44 -0700161 public ActionBarImpl(Activity activity) {
Adam Powell661c9082010-07-02 10:09:44 -0700162 mActivity = activity;
Adam Powelle6ec7322010-12-07 15:29:26 -0800163 Window window = activity.getWindow();
164 View decor = window.getDecorView();
Dianne Hackborndf7221c2013-02-26 14:53:55 -0800165 boolean overlayMode = mActivity.getWindow().hasFeature(Window.FEATURE_ACTION_BAR_OVERLAY);
Adam Powell9b0dc282013-07-31 13:58:43 -0700166 init(decor);
Dianne Hackborndf7221c2013-02-26 14:53:55 -0800167 if (!overlayMode) {
Adam Powelle6ec7322010-12-07 15:29:26 -0800168 mContentView = decor.findViewById(android.R.id.content);
169 }
Adam Powelldec9dfd2010-08-09 15:27:54 -0700170 }
171
172 public ActionBarImpl(Dialog dialog) {
173 mDialog = dialog;
Adam Powell9b0dc282013-07-31 13:58:43 -0700174 init(dialog.getWindow().getDecorView());
Adam Powelldec9dfd2010-08-09 15:27:54 -0700175 }
176
Adam Powell9b0dc282013-07-31 13:58:43 -0700177 private void init(View decor) {
Adam Powelldec9dfd2010-08-09 15:27:54 -0700178 mContext = decor.getContext();
Dianne Hackborn3a3a6cf2012-03-26 10:24:04 -0700179 mOverlayLayout = (ActionBarOverlayLayout) decor.findViewById(
180 com.android.internal.R.id.action_bar_overlay_layout);
181 if (mOverlayLayout != null) {
Adam Powell9b0dc282013-07-31 13:58:43 -0700182 mOverlayLayout.setActionBar(this);
Dianne Hackborn3a3a6cf2012-03-26 10:24:04 -0700183 }
Adam Powell89e06452010-06-23 20:24:52 -0700184 mActionView = (ActionBarView) decor.findViewById(com.android.internal.R.id.action_bar);
Adam Powell640a66e2011-04-29 10:18:53 -0700185 mContextView = (ActionBarContextView) decor.findViewById(
Adam Powell89e06452010-06-23 20:24:52 -0700186 com.android.internal.R.id.action_context_bar);
Adam Powell01feaee2011-02-10 15:05:05 -0800187 mContainerView = (ActionBarContainer) decor.findViewById(
Adam Powelld8b3f2e2010-12-02 13:37:03 -0800188 com.android.internal.R.id.action_bar_container);
Adam Powell640a66e2011-04-29 10:18:53 -0700189 mSplitView = (ActionBarContainer) decor.findViewById(
190 com.android.internal.R.id.split_action_bar);
Steve Block08f194b2010-08-24 18:20:48 +0100191
Adam Powell640a66e2011-04-29 10:18:53 -0700192 if (mActionView == null || mContextView == null || mContainerView == null) {
Adam Powell89e06452010-06-23 20:24:52 -0700193 throw new IllegalStateException(getClass().getSimpleName() + " can only be used " +
194 "with a compatible window decor layout");
195 }
Adam Powell0e94b512010-06-29 17:58:20 -0700196
Adam Powell640a66e2011-04-29 10:18:53 -0700197 mActionView.setContextView(mContextView);
Adam Powell9b4bee02011-04-27 19:24:47 -0700198 mContextDisplayMode = mActionView.isSplitActionBar() ?
199 CONTEXT_DISPLAY_SPLIT : CONTEXT_DISPLAY_NORMAL;
Adam Powelldae78242011-04-25 15:23:41 -0700200
Adam Powelld40423a2012-05-02 14:06:03 -0700201 // This was initially read from the action bar style
202 final int current = mActionView.getDisplayOptions();
203 final boolean homeAsUp = (current & DISPLAY_HOME_AS_UP) != 0;
204 if (homeAsUp) {
205 mDisplayHomeAsUpSet = true;
206 }
207
Adam Powellb8139af2012-04-19 13:52:46 -0700208 ActionBarPolicy abp = ActionBarPolicy.get(mContext);
Adam Powelld40423a2012-05-02 14:06:03 -0700209 setHomeButtonEnabled(abp.enableHomeButtonByDefault() || homeAsUp);
Adam Powellb8139af2012-04-19 13:52:46 -0700210 setHasEmbeddedTabs(abp.hasEmbeddedTabs());
Adam Powellf8ac6b72011-05-23 18:14:09 -0700211 }
212
213 public void onConfigurationChanged(Configuration newConfig) {
Adam Powellb8139af2012-04-19 13:52:46 -0700214 setHasEmbeddedTabs(ActionBarPolicy.get(mContext).hasEmbeddedTabs());
Adam Powellf5645cb2011-08-10 22:49:02 -0700215 }
Adam Powellf8ac6b72011-05-23 18:14:09 -0700216
Adam Powellf5645cb2011-08-10 22:49:02 -0700217 private void setHasEmbeddedTabs(boolean hasEmbeddedTabs) {
218 mHasEmbeddedTabs = hasEmbeddedTabs;
Adam Powellf8ac6b72011-05-23 18:14:09 -0700219 // Switch tab layout configuration if needed
220 if (!mHasEmbeddedTabs) {
221 mActionView.setEmbeddedTabView(null);
222 mContainerView.setTabContainer(mTabScrollView);
223 } else {
224 mContainerView.setTabContainer(null);
Adam Powellf8ac6b72011-05-23 18:14:09 -0700225 mActionView.setEmbeddedTabView(mTabScrollView);
226 }
Adam Powellf5645cb2011-08-10 22:49:02 -0700227 final boolean isInTabMode = getNavigationMode() == NAVIGATION_MODE_TABS;
228 if (mTabScrollView != null) {
Dianne Hackborn3a3a6cf2012-03-26 10:24:04 -0700229 if (isInTabMode) {
230 mTabScrollView.setVisibility(View.VISIBLE);
231 if (mOverlayLayout != null) {
232 mOverlayLayout.requestFitSystemWindows();
233 }
234 } else {
235 mTabScrollView.setVisibility(View.GONE);
236 }
Adam Powellf5645cb2011-08-10 22:49:02 -0700237 }
238 mActionView.setCollapsable(!mHasEmbeddedTabs && isInTabMode);
Adam Powellf8ac6b72011-05-23 18:14:09 -0700239 }
240
Dianne Hackborn3a3a6cf2012-03-26 10:24:04 -0700241 public boolean hasNonEmbeddedTabs() {
242 return !mHasEmbeddedTabs && getNavigationMode() == NAVIGATION_MODE_TABS;
243 }
244
Adam Powellf8ac6b72011-05-23 18:14:09 -0700245 private void ensureTabsExist() {
246 if (mTabScrollView != null) {
247 return;
248 }
249
Adam Powellf5645cb2011-08-10 22:49:02 -0700250 ScrollingTabContainerView tabScroller = new ScrollingTabContainerView(mContext);
Adam Powellf8ac6b72011-05-23 18:14:09 -0700251
252 if (mHasEmbeddedTabs) {
253 tabScroller.setVisibility(View.VISIBLE);
254 mActionView.setEmbeddedTabView(tabScroller);
255 } else {
Dianne Hackborn3a3a6cf2012-03-26 10:24:04 -0700256 if (getNavigationMode() == NAVIGATION_MODE_TABS) {
257 tabScroller.setVisibility(View.VISIBLE);
258 if (mOverlayLayout != null) {
259 mOverlayLayout.requestFitSystemWindows();
260 }
261 } else {
262 tabScroller.setVisibility(View.GONE);
263 }
Adam Powelldae78242011-04-25 15:23:41 -0700264 mContainerView.setTabContainer(tabScroller);
Adam Powelldae78242011-04-25 15:23:41 -0700265 }
Adam Powellf8ac6b72011-05-23 18:14:09 -0700266 mTabScrollView = tabScroller;
Adam Powell89e06452010-06-23 20:24:52 -0700267 }
268
Adam Powell060e3ca2011-07-19 20:39:16 -0700269 void completeDeferredDestroyActionMode() {
270 if (mDeferredModeDestroyCallback != null) {
271 mDeferredModeDestroyCallback.onDestroyActionMode(mDeferredDestroyActionMode);
272 mDeferredDestroyActionMode = null;
273 mDeferredModeDestroyCallback = null;
274 }
275 }
276
Dianne Hackborn3a3a6cf2012-03-26 10:24:04 -0700277 public void setWindowVisibility(int visibility) {
278 mCurWindowVisibility = visibility;
279 }
280
Adam Powell50efbed2011-02-08 16:20:15 -0800281 /**
282 * Enables or disables animation between show/hide states.
283 * If animation is disabled using this method, animations in progress
284 * will be finished.
285 *
286 * @param enabled true to animate, false to not animate.
287 */
288 public void setShowHideAnimationEnabled(boolean enabled) {
289 mShowHideAnimationEnabled = enabled;
Adam Powell07e1f982011-03-24 11:11:15 -0700290 if (!enabled && mCurrentShowAnim != null) {
291 mCurrentShowAnim.end();
Adam Powell50efbed2011-02-08 16:20:15 -0800292 }
293 }
294
Adam Powell8515ee82010-11-30 14:09:55 -0800295 public void addOnMenuVisibilityListener(OnMenuVisibilityListener listener) {
296 mMenuVisibilityListeners.add(listener);
297 }
298
299 public void removeOnMenuVisibilityListener(OnMenuVisibilityListener listener) {
300 mMenuVisibilityListeners.remove(listener);
301 }
302
303 public void dispatchMenuVisibilityChanged(boolean isVisible) {
304 if (isVisible == mLastMenuVisibility) {
305 return;
306 }
307 mLastMenuVisibility = isVisible;
308
309 final int count = mMenuVisibilityListeners.size();
310 for (int i = 0; i < count; i++) {
311 mMenuVisibilityListeners.get(i).onMenuVisibilityChanged(isVisible);
312 }
313 }
314
Adam Powella66c7b02010-07-28 15:28:25 -0700315 @Override
Adam Powell3f476b32011-01-03 19:25:36 -0800316 public void setCustomView(int resId) {
Adam Powellf2423682011-08-11 14:29:45 -0700317 setCustomView(LayoutInflater.from(getThemedContext()).inflate(resId, mActionView, false));
Adam Powell3f476b32011-01-03 19:25:36 -0800318 }
319
320 @Override
321 public void setDisplayUseLogoEnabled(boolean useLogo) {
322 setDisplayOptions(useLogo ? DISPLAY_USE_LOGO : 0, DISPLAY_USE_LOGO);
323 }
324
325 @Override
326 public void setDisplayShowHomeEnabled(boolean showHome) {
327 setDisplayOptions(showHome ? DISPLAY_SHOW_HOME : 0, DISPLAY_SHOW_HOME);
328 }
329
330 @Override
331 public void setDisplayHomeAsUpEnabled(boolean showHomeAsUp) {
332 setDisplayOptions(showHomeAsUp ? DISPLAY_HOME_AS_UP : 0, DISPLAY_HOME_AS_UP);
333 }
334
335 @Override
336 public void setDisplayShowTitleEnabled(boolean showTitle) {
337 setDisplayOptions(showTitle ? DISPLAY_SHOW_TITLE : 0, DISPLAY_SHOW_TITLE);
338 }
339
340 @Override
341 public void setDisplayShowCustomEnabled(boolean showCustom) {
342 setDisplayOptions(showCustom ? DISPLAY_SHOW_CUSTOM : 0, DISPLAY_SHOW_CUSTOM);
343 }
344
345 @Override
Adam Powellc29f4e52011-07-13 20:40:52 -0700346 public void setHomeButtonEnabled(boolean enable) {
347 mActionView.setHomeButtonEnabled(enable);
Adam Powelldae78242011-04-25 15:23:41 -0700348 }
349
350 @Override
Adam Powella66c7b02010-07-28 15:28:25 -0700351 public void setTitle(int resId) {
Adam Powelldec9dfd2010-08-09 15:27:54 -0700352 setTitle(mContext.getString(resId));
Adam Powella66c7b02010-07-28 15:28:25 -0700353 }
354
355 @Override
356 public void setSubtitle(int resId) {
Adam Powelldec9dfd2010-08-09 15:27:54 -0700357 setSubtitle(mContext.getString(resId));
Adam Powella66c7b02010-07-28 15:28:25 -0700358 }
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) {
1086 return setIcon(mContext.getResources().getDrawable(resId));
1087 }
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}