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