2 * Copyright (C) 2010 The Android Open Source Project
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
17 package com
.actionbarsherlock
.internal
.app
;
19 import java
.lang
.ref
.WeakReference
;
20 import java
.util
.ArrayList
;
21 import android
.app
.Activity
;
22 import android
.app
.Dialog
;
23 import android
.content
.Context
;
24 import android
.content
.res
.Configuration
;
25 import android
.content
.res
.Resources
;
26 import android
.graphics
.drawable
.Drawable
;
27 import android
.os
.Build
;
28 import android
.os
.Handler
;
29 import android
.support
.v4
.app
.FragmentActivity
;
30 import android
.support
.v4
.app
.FragmentTransaction
;
31 import android
.util
.TypedValue
;
32 import android
.view
.ContextThemeWrapper
;
33 import android
.view
.LayoutInflater
;
34 import android
.view
.View
;
35 import android
.view
.Window
;
36 import android
.view
.accessibility
.AccessibilityEvent
;
37 import android
.widget
.SpinnerAdapter
;
38 import com
.actionbarsherlock
.R
;
39 import com
.actionbarsherlock
.app
.ActionBar
;
40 import com
.actionbarsherlock
.internal
.nineoldandroids
.animation
.Animator
;
41 import com
.actionbarsherlock
.internal
.nineoldandroids
.animation
.AnimatorListenerAdapter
;
42 import com
.actionbarsherlock
.internal
.nineoldandroids
.animation
.AnimatorSet
;
43 import com
.actionbarsherlock
.internal
.nineoldandroids
.animation
.ObjectAnimator
;
44 import com
.actionbarsherlock
.internal
.nineoldandroids
.animation
.Animator
.AnimatorListener
;
45 import com
.actionbarsherlock
.internal
.nineoldandroids
.widget
.NineFrameLayout
;
46 import com
.actionbarsherlock
.internal
.view
.menu
.MenuBuilder
;
47 import com
.actionbarsherlock
.internal
.view
.menu
.MenuPopupHelper
;
48 import com
.actionbarsherlock
.internal
.view
.menu
.SubMenuBuilder
;
49 import com
.actionbarsherlock
.internal
.widget
.ActionBarContainer
;
50 import com
.actionbarsherlock
.internal
.widget
.ActionBarContextView
;
51 import com
.actionbarsherlock
.internal
.widget
.ActionBarView
;
52 import com
.actionbarsherlock
.internal
.widget
.ScrollingTabContainerView
;
53 import com
.actionbarsherlock
.view
.ActionMode
;
54 import com
.actionbarsherlock
.view
.Menu
;
55 import com
.actionbarsherlock
.view
.MenuInflater
;
56 import com
.actionbarsherlock
.view
.MenuItem
;
57 import static com
.actionbarsherlock
.internal
.ResourcesCompat
.getResources_getBoolean
;
60 * ActionBarImpl is the ActionBar implementation used
61 * by devices of all screen sizes. If it detects a compatible decor,
62 * it will split contextual modes across both the ActionBarView at
63 * the top of the screen and a horizontal LinearLayout at the bottom
64 * which is normally hidden.
66 public class ActionBarImpl
extends ActionBar
{
67 //UNUSED private static final String TAG = "ActionBarImpl";
69 private Context mContext
;
70 private Context mThemedContext
;
71 private Activity mActivity
;
72 //UNUSED private Dialog mDialog;
74 private ActionBarContainer mContainerView
;
75 private ActionBarView mActionView
;
76 private ActionBarContextView mContextView
;
77 private ActionBarContainer mSplitView
;
78 private NineFrameLayout mContentView
;
79 private ScrollingTabContainerView mTabScrollView
;
81 private ArrayList
<TabImpl
> mTabs
= new ArrayList
<TabImpl
>();
83 private TabImpl mSelectedTab
;
84 private int mSavedTabPosition
= INVALID_POSITION
;
86 ActionModeImpl mActionMode
;
87 ActionMode mDeferredDestroyActionMode
;
88 ActionMode
.Callback mDeferredModeDestroyCallback
;
90 private boolean mLastMenuVisibility
;
91 private ArrayList
<OnMenuVisibilityListener
> mMenuVisibilityListeners
=
92 new ArrayList
<OnMenuVisibilityListener
>();
94 private static final int CONTEXT_DISPLAY_NORMAL
= 0;
95 private static final int CONTEXT_DISPLAY_SPLIT
= 1;
97 private static final int INVALID_POSITION
= -1;
99 private int mContextDisplayMode
;
100 private boolean mHasEmbeddedTabs
;
102 final Handler mHandler
= new Handler();
103 Runnable mTabSelector
;
105 private Animator mCurrentShowAnim
;
106 private Animator mCurrentModeAnim
;
107 private boolean mShowHideAnimationEnabled
;
108 boolean mWasHiddenBeforeMode
;
110 final AnimatorListener mHideListener
= new AnimatorListenerAdapter() {
112 public void onAnimationEnd(Animator animation
) {
113 if (mContentView
!= null
) {
114 mContentView
.setTranslationY(0);
115 mContainerView
.setTranslationY(0);
117 if (mSplitView
!= null
&& mContextDisplayMode
== CONTEXT_DISPLAY_SPLIT
) {
118 mSplitView
.setVisibility(View
.GONE
);
120 mContainerView
.setVisibility(View
.GONE
);
121 mContainerView
.setTransitioning(false
);
122 mCurrentShowAnim
= null
;
123 completeDeferredDestroyActionMode();
127 final AnimatorListener mShowListener
= new AnimatorListenerAdapter() {
129 public void onAnimationEnd(Animator animation
) {
130 mCurrentShowAnim
= null
;
131 mContainerView
.requestLayout();
135 public ActionBarImpl(Activity activity
, int features
) {
136 mActivity
= activity
;
137 Window window
= activity
.getWindow();
138 View decor
= window
.getDecorView();
141 //window.hasFeature() workaround for pre-3.0
142 if ((features
& (1 << Window
.FEATURE_ACTION_BAR_OVERLAY
)) == 0) {
143 mContentView
= (NineFrameLayout
)decor
.findViewById(android
.R
.id
.content
);
147 public ActionBarImpl(Dialog dialog
) {
148 //UNUSED mDialog = dialog;
149 init(dialog
.getWindow().getDecorView());
152 private void init(View decor
) {
153 mContext
= decor
.getContext();
154 mActionView
= (ActionBarView
) decor
.findViewById(R
.id
.abs__action_bar
);
155 mContextView
= (ActionBarContextView
) decor
.findViewById(
156 R
.id
.abs__action_context_bar
);
157 mContainerView
= (ActionBarContainer
) decor
.findViewById(
158 R
.id
.abs__action_bar_container
);
159 mSplitView
= (ActionBarContainer
) decor
.findViewById(
160 R
.id
.abs__split_action_bar
);
162 if (mActionView
== null
|| mContextView
== null
|| mContainerView
== null
) {
163 throw new IllegalStateException(getClass().getSimpleName() + " can only be used " +
164 "with a compatible window decor layout");
167 mActionView
.setContextView(mContextView
);
168 mContextDisplayMode
= mActionView
.isSplitActionBar() ?
169 CONTEXT_DISPLAY_SPLIT
: CONTEXT_DISPLAY_NORMAL
;
171 // Older apps get the home button interaction enabled by default.
172 // Newer apps need to enable it explicitly.
173 setHomeButtonEnabled(mContext
.getApplicationInfo().targetSdkVersion
< 14);
175 setHasEmbeddedTabs(getResources_getBoolean(mContext
,
176 R
.bool
.abs__action_bar_embed_tabs
));
179 public void onConfigurationChanged(Configuration newConfig
) {
180 setHasEmbeddedTabs(getResources_getBoolean(mContext
,
181 R
.bool
.abs__action_bar_embed_tabs
));
183 //Manually dispatch a configuration change to the action bar view on pre-2.2
184 if (Build
.VERSION
.SDK_INT
< Build
.VERSION_CODES
.FROYO
) {
185 mActionView
.onConfigurationChanged(newConfig
);
186 if (mContextView
!= null
) {
187 mContextView
.onConfigurationChanged(newConfig
);
192 private void setHasEmbeddedTabs(boolean hasEmbeddedTabs
) {
193 mHasEmbeddedTabs
= hasEmbeddedTabs
;
194 // Switch tab layout configuration if needed
195 if (!mHasEmbeddedTabs
) {
196 mActionView
.setEmbeddedTabView(null
);
197 mContainerView
.setTabContainer(mTabScrollView
);
199 mContainerView
.setTabContainer(null
);
200 mActionView
.setEmbeddedTabView(mTabScrollView
);
202 final boolean isInTabMode
= getNavigationMode() == NAVIGATION_MODE_TABS
;
203 if (mTabScrollView
!= null
) {
204 mTabScrollView
.setVisibility(isInTabMode ? View
.VISIBLE
: View
.GONE
);
206 mActionView
.setCollapsable(!mHasEmbeddedTabs
&& isInTabMode
);
209 private void ensureTabsExist() {
210 if (mTabScrollView
!= null
) {
214 ScrollingTabContainerView tabScroller
= new ScrollingTabContainerView(mContext
);
216 if (mHasEmbeddedTabs
) {
217 tabScroller
.setVisibility(View
.VISIBLE
);
218 mActionView
.setEmbeddedTabView(tabScroller
);
220 tabScroller
.setVisibility(getNavigationMode() == NAVIGATION_MODE_TABS ?
221 View
.VISIBLE
: View
.GONE
);
222 mContainerView
.setTabContainer(tabScroller
);
224 mTabScrollView
= tabScroller
;
227 void completeDeferredDestroyActionMode() {
228 if (mDeferredModeDestroyCallback
!= null
) {
229 mDeferredModeDestroyCallback
.onDestroyActionMode(mDeferredDestroyActionMode
);
230 mDeferredDestroyActionMode
= null
;
231 mDeferredModeDestroyCallback
= null
;
236 * Enables or disables animation between show/hide states.
237 * If animation is disabled using this method, animations in progress
240 * @param enabled true to animate, false to not animate.
242 public void setShowHideAnimationEnabled(boolean enabled
) {
243 mShowHideAnimationEnabled
= enabled
;
244 if (!enabled
&& mCurrentShowAnim
!= null
) {
245 mCurrentShowAnim
.end();
249 public void addOnMenuVisibilityListener(OnMenuVisibilityListener listener
) {
250 mMenuVisibilityListeners
.add(listener
);
253 public void removeOnMenuVisibilityListener(OnMenuVisibilityListener listener
) {
254 mMenuVisibilityListeners
.remove(listener
);
257 public void dispatchMenuVisibilityChanged(boolean isVisible
) {
258 if (isVisible
== mLastMenuVisibility
) {
261 mLastMenuVisibility
= isVisible
;
263 final int count
= mMenuVisibilityListeners
.size();
264 for (int i
= 0; i
< count
; i
++) {
265 mMenuVisibilityListeners
.get(i
).onMenuVisibilityChanged(isVisible
);
270 public void setCustomView(int resId
) {
271 setCustomView(LayoutInflater
.from(getThemedContext()).inflate(resId
, mActionView
, false
));
275 public void setDisplayUseLogoEnabled(boolean useLogo
) {
276 setDisplayOptions(useLogo ? DISPLAY_USE_LOGO
: 0, DISPLAY_USE_LOGO
);
280 public void setDisplayShowHomeEnabled(boolean showHome
) {
281 setDisplayOptions(showHome ? DISPLAY_SHOW_HOME
: 0, DISPLAY_SHOW_HOME
);
285 public void setDisplayHomeAsUpEnabled(boolean showHomeAsUp
) {
286 setDisplayOptions(showHomeAsUp ? DISPLAY_HOME_AS_UP
: 0, DISPLAY_HOME_AS_UP
);
290 public void setDisplayShowTitleEnabled(boolean showTitle
) {
291 setDisplayOptions(showTitle ? DISPLAY_SHOW_TITLE
: 0, DISPLAY_SHOW_TITLE
);
295 public void setDisplayShowCustomEnabled(boolean showCustom
) {
296 setDisplayOptions(showCustom ? DISPLAY_SHOW_CUSTOM
: 0, DISPLAY_SHOW_CUSTOM
);
300 public void setHomeButtonEnabled(boolean enable
) {
301 mActionView
.setHomeButtonEnabled(enable
);
305 public void setTitle(int resId
) {
306 setTitle(mContext
.getString(resId
));
310 public void setSubtitle(int resId
) {
311 setSubtitle(mContext
.getString(resId
));
314 public void setSelectedNavigationItem(int position
) {
315 switch (mActionView
.getNavigationMode()) {
316 case NAVIGATION_MODE_TABS
:
317 selectTab(mTabs
.get(position
));
319 case NAVIGATION_MODE_LIST
:
320 mActionView
.setDropdownSelectedPosition(position
);
323 throw new IllegalStateException(
324 "setSelectedNavigationIndex not valid for current navigation mode");
328 public void removeAllTabs() {
332 private void cleanupTabs() {
333 if (mSelectedTab
!= null
) {
337 if (mTabScrollView
!= null
) {
338 mTabScrollView
.removeAllTabs();
340 mSavedTabPosition
= INVALID_POSITION
;
343 public void setTitle(CharSequence title
) {
344 mActionView
.setTitle(title
);
347 public void setSubtitle(CharSequence subtitle
) {
348 mActionView
.setSubtitle(subtitle
);
351 public void setDisplayOptions(int options
) {
352 mActionView
.setDisplayOptions(options
);
355 public void setDisplayOptions(int options
, int mask
) {
356 final int current
= mActionView
.getDisplayOptions();
357 mActionView
.setDisplayOptions((options
& mask
) | (current
& ~mask
));
360 public void setBackgroundDrawable(Drawable d
) {
361 mContainerView
.setPrimaryBackground(d
);
364 public void setStackedBackgroundDrawable(Drawable d
) {
365 mContainerView
.setStackedBackground(d
);
368 public void setSplitBackgroundDrawable(Drawable d
) {
369 if (mSplitView
!= null
) {
370 mSplitView
.setSplitBackground(d
);
374 public View
getCustomView() {
375 return mActionView
.getCustomNavigationView();
378 public CharSequence
getTitle() {
379 return mActionView
.getTitle();
382 public CharSequence
getSubtitle() {
383 return mActionView
.getSubtitle();
386 public int getNavigationMode() {
387 return mActionView
.getNavigationMode();
390 public int getDisplayOptions() {
391 return mActionView
.getDisplayOptions();
394 public ActionMode
startActionMode(ActionMode
.Callback callback
) {
395 boolean wasHidden
= false
;
396 if (mActionMode
!= null
) {
397 wasHidden
= mWasHiddenBeforeMode
;
398 mActionMode
.finish();
401 mContextView
.killMode();
402 ActionModeImpl mode
= new ActionModeImpl(callback
);
403 if (mode
.dispatchOnCreate()) {
404 mWasHiddenBeforeMode
= !isShowing() || wasHidden
;
406 mContextView
.initForMode(mode
);
408 if (mSplitView
!= null
&& mContextDisplayMode
== CONTEXT_DISPLAY_SPLIT
) {
410 mSplitView
.setVisibility(View
.VISIBLE
);
412 mContextView
.sendAccessibilityEvent(AccessibilityEvent
.TYPE_WINDOW_STATE_CHANGED
);
419 private void configureTab(Tab tab
, int position
) {
420 final TabImpl tabi
= (TabImpl
) tab
;
421 final ActionBar
.TabListener callback
= tabi
.getCallback();
423 if (callback
== null
) {
424 throw new IllegalStateException("Action Bar Tab must have a Callback");
427 tabi
.setPosition(position
);
428 mTabs
.add(position
, tabi
);
430 final int count
= mTabs
.size();
431 for (int i
= position
+ 1; i
< count
; i
++) {
432 mTabs
.get(i
).setPosition(i
);
437 public void addTab(Tab tab
) {
438 addTab(tab
, mTabs
.isEmpty());
442 public void addTab(Tab tab
, int position
) {
443 addTab(tab
, position
, mTabs
.isEmpty());
447 public void addTab(Tab tab
, boolean setSelected
) {
449 mTabScrollView
.addTab(tab
, setSelected
);
450 configureTab(tab
, mTabs
.size());
457 public void addTab(Tab tab
, int position
, boolean setSelected
) {
459 mTabScrollView
.addTab(tab
, position
, setSelected
);
460 configureTab(tab
, position
);
467 public Tab
newTab() {
468 return new TabImpl();
472 public void removeTab(Tab tab
) {
473 removeTabAt(tab
.getPosition());
477 public void removeTabAt(int position
) {
478 if (mTabScrollView
== null
) {
479 // No tabs around to remove
483 int selectedTabPosition
= mSelectedTab
!= null
484 ? mSelectedTab
.getPosition() : mSavedTabPosition
;
485 mTabScrollView
.removeTabAt(position
);
486 TabImpl removedTab
= mTabs
.remove(position
);
487 if (removedTab
!= null
) {
488 removedTab
.setPosition(-1);
491 final int newTabCount
= mTabs
.size();
492 for (int i
= position
; i
< newTabCount
; i
++) {
493 mTabs
.get(i
).setPosition(i
);
496 if (selectedTabPosition
== position
) {
497 selectTab(mTabs
.isEmpty() ? null
: mTabs
.get(Math
.max(0, position
- 1)));
502 public void selectTab(Tab tab
) {
503 if (getNavigationMode() != NAVIGATION_MODE_TABS
) {
504 mSavedTabPosition
= tab
!= null ? tab
.getPosition() : INVALID_POSITION
;
508 FragmentTransaction trans
= null
;
509 if (mActivity
instanceof FragmentActivity
) {
510 trans
= ((FragmentActivity
)mActivity
).getSupportFragmentManager().beginTransaction()
511 .disallowAddToBackStack();
514 if (mSelectedTab
== tab
) {
515 if (mSelectedTab
!= null
) {
516 mSelectedTab
.getCallback().onTabReselected(mSelectedTab
, trans
);
517 mTabScrollView
.animateToTab(tab
.getPosition());
520 mTabScrollView
.setTabSelected(tab
!= null ? tab
.getPosition() : Tab
.INVALID_POSITION
);
521 if (mSelectedTab
!= null
) {
522 mSelectedTab
.getCallback().onTabUnselected(mSelectedTab
, trans
);
524 mSelectedTab
= (TabImpl
) tab
;
525 if (mSelectedTab
!= null
) {
526 mSelectedTab
.getCallback().onTabSelected(mSelectedTab
, trans
);
530 if (trans
!= null
&& !trans
.isEmpty()) {
536 public Tab
getSelectedTab() {
541 public int getHeight() {
542 return mContainerView
.getHeight();
550 void show(boolean markHiddenBeforeMode
) {
551 if (mCurrentShowAnim
!= null
) {
552 mCurrentShowAnim
.end();
554 if (mContainerView
.getVisibility() == View
.VISIBLE
) {
555 if (markHiddenBeforeMode
) mWasHiddenBeforeMode
= false
;
558 mContainerView
.setVisibility(View
.VISIBLE
);
560 if (mShowHideAnimationEnabled
) {
561 mContainerView
.setAlpha(0);
562 AnimatorSet anim
= new AnimatorSet();
563 AnimatorSet
.Builder b
= anim
.play(ObjectAnimator
.ofFloat(mContainerView
, "alpha", 1));
564 if (mContentView
!= null
) {
565 b
.with(ObjectAnimator
.ofFloat(mContentView
, "translationY",
566 -mContainerView
.getHeight(), 0));
567 mContainerView
.setTranslationY(-mContainerView
.getHeight());
568 b
.with(ObjectAnimator
.ofFloat(mContainerView
, "translationY", 0));
570 if (mSplitView
!= null
&& mContextDisplayMode
== CONTEXT_DISPLAY_SPLIT
) {
571 mSplitView
.setAlpha(0);
572 mSplitView
.setVisibility(View
.VISIBLE
);
573 b
.with(ObjectAnimator
.ofFloat(mSplitView
, "alpha", 1));
575 anim
.addListener(mShowListener
);
576 mCurrentShowAnim
= anim
;
579 mContainerView
.setAlpha(1);
580 mContainerView
.setTranslationY(0);
581 mShowListener
.onAnimationEnd(null
);
587 if (mCurrentShowAnim
!= null
) {
588 mCurrentShowAnim
.end();
590 if (mContainerView
.getVisibility() == View
.GONE
) {
594 if (mShowHideAnimationEnabled
) {
595 mContainerView
.setAlpha(1);
596 mContainerView
.setTransitioning(true
);
597 AnimatorSet anim
= new AnimatorSet();
598 AnimatorSet
.Builder b
= anim
.play(ObjectAnimator
.ofFloat(mContainerView
, "alpha", 0));
599 if (mContentView
!= null
) {
600 b
.with(ObjectAnimator
.ofFloat(mContentView
, "translationY",
601 0, -mContainerView
.getHeight()));
602 b
.with(ObjectAnimator
.ofFloat(mContainerView
, "translationY",
603 -mContainerView
.getHeight()));
605 if (mSplitView
!= null
&& mSplitView
.getVisibility() == View
.VISIBLE
) {
606 mSplitView
.setAlpha(1);
607 b
.with(ObjectAnimator
.ofFloat(mSplitView
, "alpha", 0));
609 anim
.addListener(mHideListener
);
610 mCurrentShowAnim
= anim
;
613 mHideListener
.onAnimationEnd(null
);
617 public boolean isShowing() {
618 return mContainerView
.getVisibility() == View
.VISIBLE
;
621 void animateToMode(boolean toActionMode
) {
625 if (mCurrentModeAnim
!= null
) {
626 mCurrentModeAnim
.end();
629 mActionView
.animateToVisibility(toActionMode ? View
.GONE
: View
.VISIBLE
);
630 mContextView
.animateToVisibility(toActionMode ? View
.VISIBLE
: View
.GONE
);
631 if (mTabScrollView
!= null
&& !mActionView
.hasEmbeddedTabs() && mActionView
.isCollapsed()) {
632 mTabScrollView
.animateToVisibility(toActionMode ? View
.GONE
: View
.VISIBLE
);
636 public Context
getThemedContext() {
637 if (mThemedContext
== null
) {
638 TypedValue outValue
= new TypedValue();
639 Resources
.Theme currentTheme
= mContext
.getTheme();
640 currentTheme
.resolveAttribute(R
.attr
.actionBarWidgetTheme
,
642 final int targetThemeRes
= outValue
.resourceId
;
644 if (targetThemeRes
!= 0) { //XXX && mContext.getThemeResId() != targetThemeRes) {
645 mThemedContext
= new ContextThemeWrapper(mContext
, targetThemeRes
);
647 mThemedContext
= mContext
;
650 return mThemedContext
;
656 public class ActionModeImpl
extends ActionMode
implements MenuBuilder
.Callback
{
657 private ActionMode
.Callback mCallback
;
658 private MenuBuilder mMenu
;
659 private WeakReference
<View
> mCustomView
;
661 public ActionModeImpl(ActionMode
.Callback callback
) {
662 mCallback
= callback
;
663 mMenu
= new MenuBuilder(getThemedContext())
664 .setDefaultShowAsAction(MenuItem
.SHOW_AS_ACTION_IF_ROOM
);
665 mMenu
.setCallback(this);
669 public MenuInflater
getMenuInflater() {
670 return new MenuInflater(getThemedContext());
674 public Menu
getMenu() {
679 public void finish() {
680 if (mActionMode
!= this) {
681 // Not the active action mode - no-op
685 // If we were hidden before the mode was shown, defer the onDestroy
686 // callback until the animation is finished and associated relayout
687 // is about to happen. This lets apps better anticipate visibility
688 // and layout behavior.
689 if (mWasHiddenBeforeMode
) {
690 mDeferredDestroyActionMode
= this;
691 mDeferredModeDestroyCallback
= mCallback
;
693 mCallback
.onDestroyActionMode(this);
696 animateToMode(false
);
698 // Clear out the context mode views after the animation finishes
699 mContextView
.closeMode();
700 mActionView
.sendAccessibilityEvent(AccessibilityEvent
.TYPE_WINDOW_STATE_CHANGED
);
704 if (mWasHiddenBeforeMode
) {
710 public void invalidate() {
711 mMenu
.stopDispatchingItemsChanged();
713 mCallback
.onPrepareActionMode(this, mMenu
);
715 mMenu
.startDispatchingItemsChanged();
719 public boolean dispatchOnCreate() {
720 mMenu
.stopDispatchingItemsChanged();
722 return mCallback
.onCreateActionMode(this, mMenu
);
724 mMenu
.startDispatchingItemsChanged();
729 public void setCustomView(View view
) {
730 mContextView
.setCustomView(view
);
731 mCustomView
= new WeakReference
<View
>(view
);
735 public void setSubtitle(CharSequence subtitle
) {
736 mContextView
.setSubtitle(subtitle
);
740 public void setTitle(CharSequence title
) {
741 mContextView
.setTitle(title
);
745 public void setTitle(int resId
) {
746 setTitle(mContext
.getResources().getString(resId
));
750 public void setSubtitle(int resId
) {
751 setSubtitle(mContext
.getResources().getString(resId
));
755 public CharSequence
getTitle() {
756 return mContextView
.getTitle();
760 public CharSequence
getSubtitle() {
761 return mContextView
.getSubtitle();
765 public View
getCustomView() {
766 return mCustomView
!= null ? mCustomView
.get() : null
;
769 public boolean onMenuItemSelected(MenuBuilder menu
, MenuItem item
) {
770 if (mCallback
!= null
) {
771 return mCallback
.onActionItemClicked(this, item
);
777 public void onCloseMenu(MenuBuilder menu
, boolean allMenusAreClosing
) {
780 public boolean onSubMenuSelected(SubMenuBuilder subMenu
) {
781 if (mCallback
== null
) {
785 if (!subMenu
.hasVisibleItems()) {
789 new MenuPopupHelper(getThemedContext(), subMenu
).show();
793 public void onCloseSubMenu(SubMenuBuilder menu
) {
796 public void onMenuModeChange(MenuBuilder menu
) {
797 if (mCallback
== null
) {
801 mContextView
.showOverflowMenu();
808 public class TabImpl
extends ActionBar
.Tab
{
809 private ActionBar
.TabListener mCallback
;
811 private Drawable mIcon
;
812 private CharSequence mText
;
813 private CharSequence mContentDesc
;
814 private int mPosition
= -1;
815 private View mCustomView
;
818 public Object
getTag() {
823 public Tab
setTag(Object tag
) {
828 public ActionBar
.TabListener
getCallback() {
833 public Tab
setTabListener(ActionBar
.TabListener callback
) {
834 mCallback
= callback
;
839 public View
getCustomView() {
844 public Tab
setCustomView(View view
) {
846 if (mPosition
>= 0) {
847 mTabScrollView
.updateTab(mPosition
);
853 public Tab
setCustomView(int layoutResId
) {
854 return setCustomView(LayoutInflater
.from(getThemedContext())
855 .inflate(layoutResId
, null
));
859 public Drawable
getIcon() {
864 public int getPosition() {
868 public void setPosition(int position
) {
869 mPosition
= position
;
873 public CharSequence
getText() {
878 public Tab
setIcon(Drawable icon
) {
880 if (mPosition
>= 0) {
881 mTabScrollView
.updateTab(mPosition
);
887 public Tab
setIcon(int resId
) {
888 return setIcon(mContext
.getResources().getDrawable(resId
));
892 public Tab
setText(CharSequence text
) {
894 if (mPosition
>= 0) {
895 mTabScrollView
.updateTab(mPosition
);
901 public Tab
setText(int resId
) {
902 return setText(mContext
.getResources().getText(resId
));
906 public void select() {
911 public Tab
setContentDescription(int resId
) {
912 return setContentDescription(mContext
.getResources().getText(resId
));
916 public Tab
setContentDescription(CharSequence contentDesc
) {
917 mContentDesc
= contentDesc
;
918 if (mPosition
>= 0) {
919 mTabScrollView
.updateTab(mPosition
);
925 public CharSequence
getContentDescription() {
931 public void setCustomView(View view
) {
932 mActionView
.setCustomNavigationView(view
);
936 public void setCustomView(View view
, LayoutParams layoutParams
) {
937 view
.setLayoutParams(layoutParams
);
938 mActionView
.setCustomNavigationView(view
);
942 public void setListNavigationCallbacks(SpinnerAdapter adapter
, OnNavigationListener callback
) {
943 mActionView
.setDropdownAdapter(adapter
);
944 mActionView
.setCallback(callback
);
948 public int getSelectedNavigationIndex() {
949 switch (mActionView
.getNavigationMode()) {
950 case NAVIGATION_MODE_TABS
:
951 return mSelectedTab
!= null ? mSelectedTab
.getPosition() : -1;
952 case NAVIGATION_MODE_LIST
:
953 return mActionView
.getDropdownSelectedPosition();
960 public int getNavigationItemCount() {
961 switch (mActionView
.getNavigationMode()) {
962 case NAVIGATION_MODE_TABS
:
964 case NAVIGATION_MODE_LIST
:
965 SpinnerAdapter adapter
= mActionView
.getDropdownAdapter();
966 return adapter
!= null ? adapter
.getCount() : 0;
973 public int getTabCount() {
978 public void setNavigationMode(int mode
) {
979 final int oldMode
= mActionView
.getNavigationMode();
981 case NAVIGATION_MODE_TABS
:
982 mSavedTabPosition
= getSelectedNavigationIndex();
984 mTabScrollView
.setVisibility(View
.GONE
);
987 mActionView
.setNavigationMode(mode
);
989 case NAVIGATION_MODE_TABS
:
991 mTabScrollView
.setVisibility(View
.VISIBLE
);
992 if (mSavedTabPosition
!= INVALID_POSITION
) {
993 setSelectedNavigationItem(mSavedTabPosition
);
994 mSavedTabPosition
= INVALID_POSITION
;
998 mActionView
.setCollapsable(mode
== NAVIGATION_MODE_TABS
&& !mHasEmbeddedTabs
);
1002 public Tab
getTabAt(int index
) {
1003 return mTabs
.get(index
);
1008 public void setIcon(int resId
) {
1009 mActionView
.setIcon(resId
);
1013 public void setIcon(Drawable icon
) {
1014 mActionView
.setIcon(icon
);
1018 public void setLogo(int resId
) {
1019 mActionView
.setLogo(resId
);
1023 public void setLogo(Drawable logo
) {
1024 mActionView
.setLogo(logo
);