Home | History | Annotate | Download | only in app
      1 /*
      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 
     17 package com.android.internal.app;
     18 
     19 import android.animation.ValueAnimator;
     20 import android.content.res.TypedArray;
     21 import android.view.View.OnFocusChangeListener;
     22 import android.view.ViewGroup;
     23 import android.view.ViewParent;
     24 import android.widget.Toolbar;
     25 
     26 import com.android.internal.R;
     27 import com.android.internal.view.ActionBarPolicy;
     28 import com.android.internal.view.menu.MenuBuilder;
     29 import com.android.internal.view.menu.MenuPopupHelper;
     30 import com.android.internal.view.menu.SubMenuBuilder;
     31 import com.android.internal.widget.ActionBarContainer;
     32 import com.android.internal.widget.ActionBarContextView;
     33 import com.android.internal.widget.ActionBarOverlayLayout;
     34 import com.android.internal.widget.DecorToolbar;
     35 import com.android.internal.widget.ScrollingTabContainerView;
     36 
     37 import android.animation.Animator;
     38 import android.animation.Animator.AnimatorListener;
     39 import android.animation.AnimatorListenerAdapter;
     40 import android.animation.AnimatorSet;
     41 import android.animation.ObjectAnimator;
     42 import android.app.ActionBar;
     43 import android.app.Activity;
     44 import android.app.Dialog;
     45 import android.app.FragmentTransaction;
     46 import android.content.Context;
     47 import android.content.res.Configuration;
     48 import android.content.res.Resources;
     49 import android.graphics.drawable.Drawable;
     50 import android.util.TypedValue;
     51 import android.view.ActionMode;
     52 import android.view.ContextThemeWrapper;
     53 import android.view.LayoutInflater;
     54 import android.view.Menu;
     55 import android.view.MenuInflater;
     56 import android.view.MenuItem;
     57 import android.view.View;
     58 import android.view.Window;
     59 import android.view.accessibility.AccessibilityEvent;
     60 import android.view.animation.AnimationUtils;
     61 import android.widget.SpinnerAdapter;
     62 
     63 import java.lang.ref.WeakReference;
     64 import java.util.ArrayList;
     65 
     66 /**
     67  * WindowDecorActionBar is the ActionBar implementation used
     68  * by devices of all screen sizes as part of the window decor layout.
     69  * If it detects a compatible decor, it will split contextual modes
     70  * across both the ActionBarView at the top of the screen and
     71  * a horizontal LinearLayout at the bottom which is normally hidden.
     72  */
     73 public class WindowDecorActionBar extends ActionBar implements
     74         ActionBarOverlayLayout.ActionBarVisibilityCallback {
     75     private static final String TAG = "WindowDecorActionBar";
     76 
     77     private Context mContext;
     78     private Context mThemedContext;
     79     private Activity mActivity;
     80     private Dialog mDialog;
     81 
     82     private ActionBarOverlayLayout mOverlayLayout;
     83     private ActionBarContainer mContainerView;
     84     private DecorToolbar mDecorToolbar;
     85     private ActionBarContextView mContextView;
     86     private ActionBarContainer mSplitView;
     87     private View mContentView;
     88     private ScrollingTabContainerView mTabScrollView;
     89 
     90     private ArrayList<TabImpl> mTabs = new ArrayList<TabImpl>();
     91 
     92     private TabImpl mSelectedTab;
     93     private int mSavedTabPosition = INVALID_POSITION;
     94 
     95     private boolean mDisplayHomeAsUpSet;
     96 
     97     ActionMode mActionMode;
     98     ActionMode mDeferredDestroyActionMode;
     99     ActionMode.Callback mDeferredModeDestroyCallback;
    100 
    101     private boolean mLastMenuVisibility;
    102     private ArrayList<OnMenuVisibilityListener> mMenuVisibilityListeners =
    103             new ArrayList<OnMenuVisibilityListener>();
    104 
    105     private static final int CONTEXT_DISPLAY_NORMAL = 0;
    106     private static final int CONTEXT_DISPLAY_SPLIT = 1;
    107 
    108     private static final int INVALID_POSITION = -1;
    109 
    110     // The fade duration for toolbar and action bar when entering/exiting action mode.
    111     private static final long FADE_OUT_DURATION_MS = 100;
    112     private static final long FADE_IN_DURATION_MS = 200;
    113 
    114     private int mContextDisplayMode;
    115     private boolean mHasEmbeddedTabs;
    116 
    117     private int mCurWindowVisibility = View.VISIBLE;
    118 
    119     private boolean mContentAnimations = true;
    120     private boolean mHiddenByApp;
    121     private boolean mHiddenBySystem;
    122     private boolean mShowingForMode;
    123 
    124     private boolean mNowShowing = true;
    125 
    126     private Animator mCurrentShowAnim;
    127     private boolean mShowHideAnimationEnabled;
    128     boolean mHideOnContentScroll;
    129 
    130     final AnimatorListener mHideListener = new AnimatorListenerAdapter() {
    131         @Override
    132         public void onAnimationEnd(Animator animation) {
    133             if (mContentAnimations && mContentView != null) {
    134                 mContentView.setTranslationY(0);
    135                 mContainerView.setTranslationY(0);
    136             }
    137             if (mSplitView != null && mContextDisplayMode == CONTEXT_DISPLAY_SPLIT) {
    138                 mSplitView.setVisibility(View.GONE);
    139             }
    140             mContainerView.setVisibility(View.GONE);
    141             mContainerView.setTransitioning(false);
    142             mCurrentShowAnim = null;
    143             completeDeferredDestroyActionMode();
    144             if (mOverlayLayout != null) {
    145                 mOverlayLayout.requestApplyInsets();
    146             }
    147         }
    148     };
    149 
    150     final AnimatorListener mShowListener = new AnimatorListenerAdapter() {
    151         @Override
    152         public void onAnimationEnd(Animator animation) {
    153             mCurrentShowAnim = null;
    154             mContainerView.requestLayout();
    155         }
    156     };
    157 
    158     final ValueAnimator.AnimatorUpdateListener mUpdateListener =
    159             new ValueAnimator.AnimatorUpdateListener() {
    160         @Override
    161         public void onAnimationUpdate(ValueAnimator animation) {
    162             final ViewParent parent = mContainerView.getParent();
    163             ((View) parent).invalidate();
    164         }
    165     };
    166 
    167     public WindowDecorActionBar(Activity activity) {
    168         mActivity = activity;
    169         Window window = activity.getWindow();
    170         View decor = window.getDecorView();
    171         boolean overlayMode = mActivity.getWindow().hasFeature(Window.FEATURE_ACTION_BAR_OVERLAY);
    172         init(decor);
    173         if (!overlayMode) {
    174             mContentView = decor.findViewById(android.R.id.content);
    175         }
    176     }
    177 
    178     public WindowDecorActionBar(Dialog dialog) {
    179         mDialog = dialog;
    180         init(dialog.getWindow().getDecorView());
    181     }
    182 
    183     /**
    184      * Only for edit mode.
    185      * @hide
    186      */
    187     public WindowDecorActionBar(View layout) {
    188         assert layout.isInEditMode();
    189         init(layout);
    190     }
    191 
    192     private void init(View decor) {
    193         mOverlayLayout = (ActionBarOverlayLayout) decor.findViewById(
    194                 com.android.internal.R.id.decor_content_parent);
    195         if (mOverlayLayout != null) {
    196             mOverlayLayout.setActionBarVisibilityCallback(this);
    197         }
    198         mDecorToolbar = getDecorToolbar(decor.findViewById(com.android.internal.R.id.action_bar));
    199         mContextView = (ActionBarContextView) decor.findViewById(
    200                 com.android.internal.R.id.action_context_bar);
    201         mContainerView = (ActionBarContainer) decor.findViewById(
    202                 com.android.internal.R.id.action_bar_container);
    203         mSplitView = (ActionBarContainer) decor.findViewById(
    204                 com.android.internal.R.id.split_action_bar);
    205 
    206         if (mDecorToolbar == null || mContextView == null || mContainerView == null) {
    207             throw new IllegalStateException(getClass().getSimpleName() + " can only be used " +
    208                     "with a compatible window decor layout");
    209         }
    210 
    211         mContext = mDecorToolbar.getContext();
    212         mContextDisplayMode = mDecorToolbar.isSplit() ?
    213                 CONTEXT_DISPLAY_SPLIT : CONTEXT_DISPLAY_NORMAL;
    214 
    215         // This was initially read from the action bar style
    216         final int current = mDecorToolbar.getDisplayOptions();
    217         final boolean homeAsUp = (current & DISPLAY_HOME_AS_UP) != 0;
    218         if (homeAsUp) {
    219             mDisplayHomeAsUpSet = true;
    220         }
    221 
    222         ActionBarPolicy abp = ActionBarPolicy.get(mContext);
    223         setHomeButtonEnabled(abp.enableHomeButtonByDefault() || homeAsUp);
    224         setHasEmbeddedTabs(abp.hasEmbeddedTabs());
    225 
    226         final TypedArray a = mContext.obtainStyledAttributes(null,
    227                 com.android.internal.R.styleable.ActionBar,
    228                 com.android.internal.R.attr.actionBarStyle, 0);
    229         if (a.getBoolean(R.styleable.ActionBar_hideOnContentScroll, false)) {
    230             setHideOnContentScrollEnabled(true);
    231         }
    232         final int elevation = a.getDimensionPixelSize(R.styleable.ActionBar_elevation, 0);
    233         if (elevation != 0) {
    234             setElevation(elevation);
    235         }
    236         a.recycle();
    237     }
    238 
    239     private DecorToolbar getDecorToolbar(View view) {
    240         if (view instanceof DecorToolbar) {
    241             return (DecorToolbar) view;
    242         } else if (view instanceof Toolbar) {
    243             return ((Toolbar) view).getWrapper();
    244         } else {
    245             throw new IllegalStateException("Can't make a decor toolbar out of " +
    246                     view.getClass().getSimpleName());
    247         }
    248     }
    249 
    250     @Override
    251     public void setElevation(float elevation) {
    252         mContainerView.setElevation(elevation);
    253         if (mSplitView != null) {
    254             mSplitView.setElevation(elevation);
    255         }
    256     }
    257 
    258     @Override
    259     public float getElevation() {
    260         return mContainerView.getElevation();
    261     }
    262 
    263     public void onConfigurationChanged(Configuration newConfig) {
    264         setHasEmbeddedTabs(ActionBarPolicy.get(mContext).hasEmbeddedTabs());
    265     }
    266 
    267     private void setHasEmbeddedTabs(boolean hasEmbeddedTabs) {
    268         mHasEmbeddedTabs = hasEmbeddedTabs;
    269         // Switch tab layout configuration if needed
    270         if (!mHasEmbeddedTabs) {
    271             mDecorToolbar.setEmbeddedTabView(null);
    272             mContainerView.setTabContainer(mTabScrollView);
    273         } else {
    274             mContainerView.setTabContainer(null);
    275             mDecorToolbar.setEmbeddedTabView(mTabScrollView);
    276         }
    277         final boolean isInTabMode = getNavigationMode() == NAVIGATION_MODE_TABS;
    278         if (mTabScrollView != null) {
    279             if (isInTabMode) {
    280                 mTabScrollView.setVisibility(View.VISIBLE);
    281                 if (mOverlayLayout != null) {
    282                     mOverlayLayout.requestApplyInsets();
    283                 }
    284             } else {
    285                 mTabScrollView.setVisibility(View.GONE);
    286             }
    287         }
    288         mDecorToolbar.setCollapsible(!mHasEmbeddedTabs && isInTabMode);
    289         mOverlayLayout.setHasNonEmbeddedTabs(!mHasEmbeddedTabs && isInTabMode);
    290     }
    291 
    292     private void ensureTabsExist() {
    293         if (mTabScrollView != null) {
    294             return;
    295         }
    296 
    297         ScrollingTabContainerView tabScroller = new ScrollingTabContainerView(mContext);
    298 
    299         if (mHasEmbeddedTabs) {
    300             tabScroller.setVisibility(View.VISIBLE);
    301             mDecorToolbar.setEmbeddedTabView(tabScroller);
    302         } else {
    303             if (getNavigationMode() == NAVIGATION_MODE_TABS) {
    304                 tabScroller.setVisibility(View.VISIBLE);
    305                 if (mOverlayLayout != null) {
    306                     mOverlayLayout.requestApplyInsets();
    307                 }
    308             } else {
    309                 tabScroller.setVisibility(View.GONE);
    310             }
    311             mContainerView.setTabContainer(tabScroller);
    312         }
    313         mTabScrollView = tabScroller;
    314     }
    315 
    316     void completeDeferredDestroyActionMode() {
    317         if (mDeferredModeDestroyCallback != null) {
    318             mDeferredModeDestroyCallback.onDestroyActionMode(mDeferredDestroyActionMode);
    319             mDeferredDestroyActionMode = null;
    320             mDeferredModeDestroyCallback = null;
    321         }
    322     }
    323 
    324     public void onWindowVisibilityChanged(int visibility) {
    325         mCurWindowVisibility = visibility;
    326     }
    327 
    328     /**
    329      * Enables or disables animation between show/hide states.
    330      * If animation is disabled using this method, animations in progress
    331      * will be finished.
    332      *
    333      * @param enabled true to animate, false to not animate.
    334      */
    335     public void setShowHideAnimationEnabled(boolean enabled) {
    336         mShowHideAnimationEnabled = enabled;
    337         if (!enabled && mCurrentShowAnim != null) {
    338             mCurrentShowAnim.end();
    339         }
    340     }
    341 
    342     public void addOnMenuVisibilityListener(OnMenuVisibilityListener listener) {
    343         mMenuVisibilityListeners.add(listener);
    344     }
    345 
    346     public void removeOnMenuVisibilityListener(OnMenuVisibilityListener listener) {
    347         mMenuVisibilityListeners.remove(listener);
    348     }
    349 
    350     public void dispatchMenuVisibilityChanged(boolean isVisible) {
    351         if (isVisible == mLastMenuVisibility) {
    352             return;
    353         }
    354         mLastMenuVisibility = isVisible;
    355 
    356         final int count = mMenuVisibilityListeners.size();
    357         for (int i = 0; i < count; i++) {
    358             mMenuVisibilityListeners.get(i).onMenuVisibilityChanged(isVisible);
    359         }
    360     }
    361 
    362     @Override
    363     public void setCustomView(int resId) {
    364         setCustomView(LayoutInflater.from(getThemedContext()).inflate(resId,
    365                 mDecorToolbar.getViewGroup(), false));
    366     }
    367 
    368     @Override
    369     public void setDisplayUseLogoEnabled(boolean useLogo) {
    370         setDisplayOptions(useLogo ? DISPLAY_USE_LOGO : 0, DISPLAY_USE_LOGO);
    371     }
    372 
    373     @Override
    374     public void setDisplayShowHomeEnabled(boolean showHome) {
    375         setDisplayOptions(showHome ? DISPLAY_SHOW_HOME : 0, DISPLAY_SHOW_HOME);
    376     }
    377 
    378     @Override
    379     public void setDisplayHomeAsUpEnabled(boolean showHomeAsUp) {
    380         setDisplayOptions(showHomeAsUp ? DISPLAY_HOME_AS_UP : 0, DISPLAY_HOME_AS_UP);
    381     }
    382 
    383     @Override
    384     public void setDisplayShowTitleEnabled(boolean showTitle) {
    385         setDisplayOptions(showTitle ? DISPLAY_SHOW_TITLE : 0, DISPLAY_SHOW_TITLE);
    386     }
    387 
    388     @Override
    389     public void setDisplayShowCustomEnabled(boolean showCustom) {
    390         setDisplayOptions(showCustom ? DISPLAY_SHOW_CUSTOM : 0, DISPLAY_SHOW_CUSTOM);
    391     }
    392 
    393     @Override
    394     public void setHomeButtonEnabled(boolean enable) {
    395         mDecorToolbar.setHomeButtonEnabled(enable);
    396     }
    397 
    398     @Override
    399     public void setTitle(int resId) {
    400         setTitle(mContext.getString(resId));
    401     }
    402 
    403     @Override
    404     public void setSubtitle(int resId) {
    405         setSubtitle(mContext.getString(resId));
    406     }
    407 
    408     public void setSelectedNavigationItem(int position) {
    409         switch (mDecorToolbar.getNavigationMode()) {
    410         case NAVIGATION_MODE_TABS:
    411             selectTab(mTabs.get(position));
    412             break;
    413         case NAVIGATION_MODE_LIST:
    414             mDecorToolbar.setDropdownSelectedPosition(position);
    415             break;
    416         default:
    417             throw new IllegalStateException(
    418                     "setSelectedNavigationIndex not valid for current navigation mode");
    419         }
    420     }
    421 
    422     public void removeAllTabs() {
    423         cleanupTabs();
    424     }
    425 
    426     private void cleanupTabs() {
    427         if (mSelectedTab != null) {
    428             selectTab(null);
    429         }
    430         mTabs.clear();
    431         if (mTabScrollView != null) {
    432             mTabScrollView.removeAllTabs();
    433         }
    434         mSavedTabPosition = INVALID_POSITION;
    435     }
    436 
    437     public void setTitle(CharSequence title) {
    438         mDecorToolbar.setTitle(title);
    439     }
    440 
    441     @Override
    442     public void setWindowTitle(CharSequence title) {
    443         mDecorToolbar.setWindowTitle(title);
    444     }
    445 
    446     public void setSubtitle(CharSequence subtitle) {
    447         mDecorToolbar.setSubtitle(subtitle);
    448     }
    449 
    450     public void setDisplayOptions(int options) {
    451         if ((options & DISPLAY_HOME_AS_UP) != 0) {
    452             mDisplayHomeAsUpSet = true;
    453         }
    454         mDecorToolbar.setDisplayOptions(options);
    455     }
    456 
    457     public void setDisplayOptions(int options, int mask) {
    458         final int current = mDecorToolbar.getDisplayOptions();
    459         if ((mask & DISPLAY_HOME_AS_UP) != 0) {
    460             mDisplayHomeAsUpSet = true;
    461         }
    462         mDecorToolbar.setDisplayOptions((options & mask) | (current & ~mask));
    463     }
    464 
    465     public void setBackgroundDrawable(Drawable d) {
    466         mContainerView.setPrimaryBackground(d);
    467     }
    468 
    469     public void setStackedBackgroundDrawable(Drawable d) {
    470         mContainerView.setStackedBackground(d);
    471     }
    472 
    473     public void setSplitBackgroundDrawable(Drawable d) {
    474         if (mSplitView != null) {
    475             mSplitView.setSplitBackground(d);
    476         }
    477     }
    478 
    479     public View getCustomView() {
    480         return mDecorToolbar.getCustomView();
    481     }
    482 
    483     public CharSequence getTitle() {
    484         return mDecorToolbar.getTitle();
    485     }
    486 
    487     public CharSequence getSubtitle() {
    488         return mDecorToolbar.getSubtitle();
    489     }
    490 
    491     public int getNavigationMode() {
    492         return mDecorToolbar.getNavigationMode();
    493     }
    494 
    495     public int getDisplayOptions() {
    496         return mDecorToolbar.getDisplayOptions();
    497     }
    498 
    499     public ActionMode startActionMode(ActionMode.Callback callback) {
    500         if (mActionMode != null) {
    501             mActionMode.finish();
    502         }
    503 
    504         mOverlayLayout.setHideOnContentScrollEnabled(false);
    505         mContextView.killMode();
    506         ActionModeImpl mode = new ActionModeImpl(mContextView.getContext(), callback);
    507         if (mode.dispatchOnCreate()) {
    508             // This needs to be set before invalidate() so that it calls
    509             // onPrepareActionMode()
    510             mActionMode = mode;
    511             mode.invalidate();
    512             mContextView.initForMode(mode);
    513             animateToMode(true);
    514             if (mSplitView != null && mContextDisplayMode == CONTEXT_DISPLAY_SPLIT) {
    515                 // TODO animate this
    516                 if (mSplitView.getVisibility() != View.VISIBLE) {
    517                     mSplitView.setVisibility(View.VISIBLE);
    518                     if (mOverlayLayout != null) {
    519                         mOverlayLayout.requestApplyInsets();
    520                     }
    521                 }
    522             }
    523             mContextView.sendAccessibilityEvent(AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED);
    524             return mode;
    525         }
    526         return null;
    527     }
    528 
    529     private void configureTab(Tab tab, int position) {
    530         final TabImpl tabi = (TabImpl) tab;
    531         final ActionBar.TabListener callback = tabi.getCallback();
    532 
    533         if (callback == null) {
    534             throw new IllegalStateException("Action Bar Tab must have a Callback");
    535         }
    536 
    537         tabi.setPosition(position);
    538         mTabs.add(position, tabi);
    539 
    540         final int count = mTabs.size();
    541         for (int i = position + 1; i < count; i++) {
    542             mTabs.get(i).setPosition(i);
    543         }
    544     }
    545 
    546     @Override
    547     public void addTab(Tab tab) {
    548         addTab(tab, mTabs.isEmpty());
    549     }
    550 
    551     @Override
    552     public void addTab(Tab tab, int position) {
    553         addTab(tab, position, mTabs.isEmpty());
    554     }
    555 
    556     @Override
    557     public void addTab(Tab tab, boolean setSelected) {
    558         ensureTabsExist();
    559         mTabScrollView.addTab(tab, setSelected);
    560         configureTab(tab, mTabs.size());
    561         if (setSelected) {
    562             selectTab(tab);
    563         }
    564     }
    565 
    566     @Override
    567     public void addTab(Tab tab, int position, boolean setSelected) {
    568         ensureTabsExist();
    569         mTabScrollView.addTab(tab, position, setSelected);
    570         configureTab(tab, position);
    571         if (setSelected) {
    572             selectTab(tab);
    573         }
    574     }
    575 
    576     @Override
    577     public Tab newTab() {
    578         return new TabImpl();
    579     }
    580 
    581     @Override
    582     public void removeTab(Tab tab) {
    583         removeTabAt(tab.getPosition());
    584     }
    585 
    586     @Override
    587     public void removeTabAt(int position) {
    588         if (mTabScrollView == null) {
    589             // No tabs around to remove
    590             return;
    591         }
    592 
    593         int selectedTabPosition = mSelectedTab != null
    594                 ? mSelectedTab.getPosition() : mSavedTabPosition;
    595         mTabScrollView.removeTabAt(position);
    596         TabImpl removedTab = mTabs.remove(position);
    597         if (removedTab != null) {
    598             removedTab.setPosition(-1);
    599         }
    600 
    601         final int newTabCount = mTabs.size();
    602         for (int i = position; i < newTabCount; i++) {
    603             mTabs.get(i).setPosition(i);
    604         }
    605 
    606         if (selectedTabPosition == position) {
    607             selectTab(mTabs.isEmpty() ? null : mTabs.get(Math.max(0, position - 1)));
    608         }
    609     }
    610 
    611     @Override
    612     public void selectTab(Tab tab) {
    613         if (getNavigationMode() != NAVIGATION_MODE_TABS) {
    614             mSavedTabPosition = tab != null ? tab.getPosition() : INVALID_POSITION;
    615             return;
    616         }
    617 
    618         final FragmentTransaction trans = mDecorToolbar.getViewGroup().isInEditMode() ? null :
    619                 mActivity.getFragmentManager().beginTransaction().disallowAddToBackStack();
    620 
    621         if (mSelectedTab == tab) {
    622             if (mSelectedTab != null) {
    623                 mSelectedTab.getCallback().onTabReselected(mSelectedTab, trans);
    624                 mTabScrollView.animateToTab(tab.getPosition());
    625             }
    626         } else {
    627             mTabScrollView.setTabSelected(tab != null ? tab.getPosition() : Tab.INVALID_POSITION);
    628             if (mSelectedTab != null) {
    629                 mSelectedTab.getCallback().onTabUnselected(mSelectedTab, trans);
    630             }
    631             mSelectedTab = (TabImpl) tab;
    632             if (mSelectedTab != null) {
    633                 mSelectedTab.getCallback().onTabSelected(mSelectedTab, trans);
    634             }
    635         }
    636 
    637         if (trans != null && !trans.isEmpty()) {
    638             trans.commit();
    639         }
    640     }
    641 
    642     @Override
    643     public Tab getSelectedTab() {
    644         return mSelectedTab;
    645     }
    646 
    647     @Override
    648     public int getHeight() {
    649         return mContainerView.getHeight();
    650     }
    651 
    652     public void enableContentAnimations(boolean enabled) {
    653         mContentAnimations = enabled;
    654     }
    655 
    656     @Override
    657     public void show() {
    658         if (mHiddenByApp) {
    659             mHiddenByApp = false;
    660             updateVisibility(false);
    661         }
    662     }
    663 
    664     private void showForActionMode() {
    665         if (!mShowingForMode) {
    666             mShowingForMode = true;
    667             if (mOverlayLayout != null) {
    668                 mOverlayLayout.setShowingForActionMode(true);
    669             }
    670             updateVisibility(false);
    671         }
    672     }
    673 
    674     public void showForSystem() {
    675         if (mHiddenBySystem) {
    676             mHiddenBySystem = false;
    677             updateVisibility(true);
    678         }
    679     }
    680 
    681     @Override
    682     public void hide() {
    683         if (!mHiddenByApp) {
    684             mHiddenByApp = true;
    685             updateVisibility(false);
    686         }
    687     }
    688 
    689     private void hideForActionMode() {
    690         if (mShowingForMode) {
    691             mShowingForMode = false;
    692             if (mOverlayLayout != null) {
    693                 mOverlayLayout.setShowingForActionMode(false);
    694             }
    695             updateVisibility(false);
    696         }
    697     }
    698 
    699     public void hideForSystem() {
    700         if (!mHiddenBySystem) {
    701             mHiddenBySystem = true;
    702             updateVisibility(true);
    703         }
    704     }
    705 
    706     @Override
    707     public void setHideOnContentScrollEnabled(boolean hideOnContentScroll) {
    708         if (hideOnContentScroll && !mOverlayLayout.isInOverlayMode()) {
    709             throw new IllegalStateException("Action bar must be in overlay mode " +
    710                     "(Window.FEATURE_OVERLAY_ACTION_BAR) to enable hide on content scroll");
    711         }
    712         mHideOnContentScroll = hideOnContentScroll;
    713         mOverlayLayout.setHideOnContentScrollEnabled(hideOnContentScroll);
    714     }
    715 
    716     @Override
    717     public boolean isHideOnContentScrollEnabled() {
    718         return mOverlayLayout.isHideOnContentScrollEnabled();
    719     }
    720 
    721     @Override
    722     public int getHideOffset() {
    723         return mOverlayLayout.getActionBarHideOffset();
    724     }
    725 
    726     @Override
    727     public void setHideOffset(int offset) {
    728         if (offset != 0 && !mOverlayLayout.isInOverlayMode()) {
    729             throw new IllegalStateException("Action bar must be in overlay mode " +
    730                     "(Window.FEATURE_OVERLAY_ACTION_BAR) to set a non-zero hide offset");
    731         }
    732         mOverlayLayout.setActionBarHideOffset(offset);
    733     }
    734 
    735     private static boolean checkShowingFlags(boolean hiddenByApp, boolean hiddenBySystem,
    736             boolean showingForMode) {
    737         if (showingForMode) {
    738             return true;
    739         } else if (hiddenByApp || hiddenBySystem) {
    740             return false;
    741         } else {
    742             return true;
    743         }
    744     }
    745 
    746     private void updateVisibility(boolean fromSystem) {
    747         // Based on the current state, should we be hidden or shown?
    748         final boolean shown = checkShowingFlags(mHiddenByApp, mHiddenBySystem,
    749                 mShowingForMode);
    750 
    751         if (shown) {
    752             if (!mNowShowing) {
    753                 mNowShowing = true;
    754                 doShow(fromSystem);
    755             }
    756         } else {
    757             if (mNowShowing) {
    758                 mNowShowing = false;
    759                 doHide(fromSystem);
    760             }
    761         }
    762     }
    763 
    764     public void doShow(boolean fromSystem) {
    765         if (mCurrentShowAnim != null) {
    766             mCurrentShowAnim.end();
    767         }
    768         mContainerView.setVisibility(View.VISIBLE);
    769 
    770         if (mCurWindowVisibility == View.VISIBLE && (mShowHideAnimationEnabled
    771                 || fromSystem)) {
    772             mContainerView.setTranslationY(0); // because we're about to ask its window loc
    773             float startingY = -mContainerView.getHeight();
    774             if (fromSystem) {
    775                 int topLeft[] = {0, 0};
    776                 mContainerView.getLocationInWindow(topLeft);
    777                 startingY -= topLeft[1];
    778             }
    779             mContainerView.setTranslationY(startingY);
    780             AnimatorSet anim = new AnimatorSet();
    781             ObjectAnimator a = ObjectAnimator.ofFloat(mContainerView, View.TRANSLATION_Y, 0);
    782             a.addUpdateListener(mUpdateListener);
    783             AnimatorSet.Builder b = anim.play(a);
    784             if (mContentAnimations && mContentView != null) {
    785                 b.with(ObjectAnimator.ofFloat(mContentView, View.TRANSLATION_Y,
    786                         startingY, 0));
    787             }
    788             if (mSplitView != null && mContextDisplayMode == CONTEXT_DISPLAY_SPLIT) {
    789                 mSplitView.setTranslationY(mSplitView.getHeight());
    790                 mSplitView.setVisibility(View.VISIBLE);
    791                 b.with(ObjectAnimator.ofFloat(mSplitView, View.TRANSLATION_Y, 0));
    792             }
    793             anim.setInterpolator(AnimationUtils.loadInterpolator(mContext,
    794                     com.android.internal.R.interpolator.decelerate_cubic));
    795             anim.setDuration(250);
    796             // If this is being shown from the system, add a small delay.
    797             // This is because we will also be animating in the status bar,
    798             // and these two elements can't be done in lock-step.  So we give
    799             // a little time for the status bar to start its animation before
    800             // the action bar animates.  (This corresponds to the corresponding
    801             // case when hiding, where the status bar has a small delay before
    802             // starting.)
    803             anim.addListener(mShowListener);
    804             mCurrentShowAnim = anim;
    805             anim.start();
    806         } else {
    807             mContainerView.setAlpha(1);
    808             mContainerView.setTranslationY(0);
    809             if (mContentAnimations && mContentView != null) {
    810                 mContentView.setTranslationY(0);
    811             }
    812             if (mSplitView != null && mContextDisplayMode == CONTEXT_DISPLAY_SPLIT) {
    813                 mSplitView.setAlpha(1);
    814                 mSplitView.setTranslationY(0);
    815                 mSplitView.setVisibility(View.VISIBLE);
    816             }
    817             mShowListener.onAnimationEnd(null);
    818         }
    819         if (mOverlayLayout != null) {
    820             mOverlayLayout.requestApplyInsets();
    821         }
    822     }
    823 
    824     public void doHide(boolean fromSystem) {
    825         if (mCurrentShowAnim != null) {
    826             mCurrentShowAnim.end();
    827         }
    828 
    829         if (mCurWindowVisibility == View.VISIBLE && (mShowHideAnimationEnabled
    830                 || fromSystem)) {
    831             mContainerView.setAlpha(1);
    832             mContainerView.setTransitioning(true);
    833             AnimatorSet anim = new AnimatorSet();
    834             float endingY = -mContainerView.getHeight();
    835             if (fromSystem) {
    836                 int topLeft[] = {0, 0};
    837                 mContainerView.getLocationInWindow(topLeft);
    838                 endingY -= topLeft[1];
    839             }
    840             ObjectAnimator a = ObjectAnimator.ofFloat(mContainerView, View.TRANSLATION_Y, endingY);
    841             a.addUpdateListener(mUpdateListener);
    842             AnimatorSet.Builder b = anim.play(a);
    843             if (mContentAnimations && mContentView != null) {
    844                 b.with(ObjectAnimator.ofFloat(mContentView, View.TRANSLATION_Y,
    845                         0, endingY));
    846             }
    847             if (mSplitView != null && mSplitView.getVisibility() == View.VISIBLE) {
    848                 mSplitView.setAlpha(1);
    849                 b.with(ObjectAnimator.ofFloat(mSplitView, View.TRANSLATION_Y,
    850                         mSplitView.getHeight()));
    851             }
    852             anim.setInterpolator(AnimationUtils.loadInterpolator(mContext,
    853                     com.android.internal.R.interpolator.accelerate_cubic));
    854             anim.setDuration(250);
    855             anim.addListener(mHideListener);
    856             mCurrentShowAnim = anim;
    857             anim.start();
    858         } else {
    859             mHideListener.onAnimationEnd(null);
    860         }
    861     }
    862 
    863     public boolean isShowing() {
    864         final int height = getHeight();
    865         // Take into account the case where the bar has a 0 height due to not being measured yet.
    866         return mNowShowing && (height == 0 || getHideOffset() < height);
    867     }
    868 
    869     void animateToMode(boolean toActionMode) {
    870         if (toActionMode) {
    871             showForActionMode();
    872         } else {
    873             hideForActionMode();
    874         }
    875 
    876         if (shouldAnimateContextView()) {
    877             Animator fadeIn, fadeOut;
    878             if (toActionMode) {
    879                 fadeOut = mDecorToolbar.setupAnimatorToVisibility(View.GONE,
    880                         FADE_OUT_DURATION_MS);
    881                 fadeIn = mContextView.setupAnimatorToVisibility(View.VISIBLE,
    882                         FADE_IN_DURATION_MS);
    883             } else {
    884                 fadeIn = mDecorToolbar.setupAnimatorToVisibility(View.VISIBLE,
    885                         FADE_IN_DURATION_MS);
    886                 fadeOut = mContextView.setupAnimatorToVisibility(View.GONE,
    887                         FADE_OUT_DURATION_MS);
    888             }
    889             AnimatorSet set = new AnimatorSet();
    890             set.playSequentially(fadeOut, fadeIn);
    891             set.start();
    892         } else {
    893             if (toActionMode) {
    894                 mDecorToolbar.setVisibility(View.GONE);
    895                 mContextView.setVisibility(View.VISIBLE);
    896             } else {
    897                 mDecorToolbar.setVisibility(View.VISIBLE);
    898                 mContextView.setVisibility(View.GONE);
    899             }
    900         }
    901         // mTabScrollView's visibility is not affected by action mode.
    902     }
    903 
    904     private boolean shouldAnimateContextView() {
    905         // We only to animate the action mode in if the container view has already been laid out.
    906         // If it hasn't been laid out, it hasn't been drawn to screen yet.
    907         return mContainerView.isLaidOut();
    908     }
    909 
    910     public Context getThemedContext() {
    911         if (mThemedContext == null) {
    912             TypedValue outValue = new TypedValue();
    913             Resources.Theme currentTheme = mContext.getTheme();
    914             currentTheme.resolveAttribute(com.android.internal.R.attr.actionBarWidgetTheme,
    915                     outValue, true);
    916             final int targetThemeRes = outValue.resourceId;
    917 
    918             if (targetThemeRes != 0 && mContext.getThemeResId() != targetThemeRes) {
    919                 mThemedContext = new ContextThemeWrapper(mContext, targetThemeRes);
    920             } else {
    921                 mThemedContext = mContext;
    922             }
    923         }
    924         return mThemedContext;
    925     }
    926 
    927     @Override
    928     public boolean isTitleTruncated() {
    929         return mDecorToolbar != null && mDecorToolbar.isTitleTruncated();
    930     }
    931 
    932     @Override
    933     public void setHomeAsUpIndicator(Drawable indicator) {
    934         mDecorToolbar.setNavigationIcon(indicator);
    935     }
    936 
    937     @Override
    938     public void setHomeAsUpIndicator(int resId) {
    939         mDecorToolbar.setNavigationIcon(resId);
    940     }
    941 
    942     @Override
    943     public void setHomeActionContentDescription(CharSequence description) {
    944         mDecorToolbar.setNavigationContentDescription(description);
    945     }
    946 
    947     @Override
    948     public void setHomeActionContentDescription(int resId) {
    949         mDecorToolbar.setNavigationContentDescription(resId);
    950     }
    951 
    952     @Override
    953     public void onContentScrollStarted() {
    954         if (mCurrentShowAnim != null) {
    955             mCurrentShowAnim.cancel();
    956             mCurrentShowAnim = null;
    957         }
    958     }
    959 
    960     @Override
    961     public void onContentScrollStopped() {
    962     }
    963 
    964     @Override
    965     public boolean collapseActionView() {
    966         if (mDecorToolbar != null && mDecorToolbar.hasExpandedActionView()) {
    967             mDecorToolbar.collapseActionView();
    968             return true;
    969         }
    970         return false;
    971     }
    972 
    973     /** @hide */
    974     @Override
    975     public boolean requestFocus() {
    976         return requestFocus(mDecorToolbar.getViewGroup());
    977     }
    978 
    979     /**
    980      * @hide
    981      */
    982     public class ActionModeImpl extends ActionMode implements MenuBuilder.Callback {
    983         private final Context mActionModeContext;
    984         private final MenuBuilder mMenu;
    985 
    986         private ActionMode.Callback mCallback;
    987         private WeakReference<View> mCustomView;
    988 
    989         public ActionModeImpl(
    990                 Context context, ActionMode.Callback callback) {
    991             mActionModeContext = context;
    992             mCallback = callback;
    993             mMenu = new MenuBuilder(context)
    994                         .setDefaultShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM);
    995             mMenu.setCallback(this);
    996         }
    997 
    998         @Override
    999         public MenuInflater getMenuInflater() {
   1000             return new MenuInflater(mActionModeContext);
   1001         }
   1002 
   1003         @Override
   1004         public Menu getMenu() {
   1005             return mMenu;
   1006         }
   1007 
   1008         @Override
   1009         public void finish() {
   1010             if (mActionMode != this) {
   1011                 // Not the active action mode - no-op
   1012                 return;
   1013             }
   1014 
   1015             // If this change in state is going to cause the action bar
   1016             // to be hidden, defer the onDestroy callback until the animation
   1017             // is finished and associated relayout is about to happen. This lets
   1018             // apps better anticipate visibility and layout behavior.
   1019             if (!checkShowingFlags(mHiddenByApp, mHiddenBySystem, false)) {
   1020                 // With the current state but the action bar hidden, our
   1021                 // overall showing state is going to be false.
   1022                 mDeferredDestroyActionMode = this;
   1023                 mDeferredModeDestroyCallback = mCallback;
   1024             } else {
   1025                 mCallback.onDestroyActionMode(this);
   1026             }
   1027             mCallback = null;
   1028             animateToMode(false);
   1029 
   1030             // Clear out the context mode views after the animation finishes
   1031             mContextView.closeMode();
   1032             mDecorToolbar.getViewGroup().sendAccessibilityEvent(
   1033                     AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED);
   1034             mOverlayLayout.setHideOnContentScrollEnabled(mHideOnContentScroll);
   1035 
   1036             mActionMode = null;
   1037         }
   1038 
   1039         @Override
   1040         public void invalidate() {
   1041             if (mActionMode != this) {
   1042                 // Not the active action mode - no-op. It's possible we are
   1043                 // currently deferring onDestroy, so the app doesn't yet know we
   1044                 // are going away and is trying to use us. That's also a no-op.
   1045                 return;
   1046             }
   1047 
   1048             mMenu.stopDispatchingItemsChanged();
   1049             try {
   1050                 mCallback.onPrepareActionMode(this, mMenu);
   1051             } finally {
   1052                 mMenu.startDispatchingItemsChanged();
   1053             }
   1054         }
   1055 
   1056         public boolean dispatchOnCreate() {
   1057             mMenu.stopDispatchingItemsChanged();
   1058             try {
   1059                 return mCallback.onCreateActionMode(this, mMenu);
   1060             } finally {
   1061                 mMenu.startDispatchingItemsChanged();
   1062             }
   1063         }
   1064 
   1065         @Override
   1066         public void setCustomView(View view) {
   1067             mContextView.setCustomView(view);
   1068             mCustomView = new WeakReference<View>(view);
   1069         }
   1070 
   1071         @Override
   1072         public void setSubtitle(CharSequence subtitle) {
   1073             mContextView.setSubtitle(subtitle);
   1074         }
   1075 
   1076         @Override
   1077         public void setTitle(CharSequence title) {
   1078             mContextView.setTitle(title);
   1079         }
   1080 
   1081         @Override
   1082         public void setTitle(int resId) {
   1083             setTitle(mContext.getResources().getString(resId));
   1084         }
   1085 
   1086         @Override
   1087         public void setSubtitle(int resId) {
   1088             setSubtitle(mContext.getResources().getString(resId));
   1089         }
   1090 
   1091         @Override
   1092         public CharSequence getTitle() {
   1093             return mContextView.getTitle();
   1094         }
   1095 
   1096         @Override
   1097         public CharSequence getSubtitle() {
   1098             return mContextView.getSubtitle();
   1099         }
   1100 
   1101         @Override
   1102         public void setTitleOptionalHint(boolean titleOptional) {
   1103             super.setTitleOptionalHint(titleOptional);
   1104             mContextView.setTitleOptional(titleOptional);
   1105         }
   1106 
   1107         @Override
   1108         public boolean isTitleOptional() {
   1109             return mContextView.isTitleOptional();
   1110         }
   1111 
   1112         @Override
   1113         public View getCustomView() {
   1114             return mCustomView != null ? mCustomView.get() : null;
   1115         }
   1116 
   1117         public boolean onMenuItemSelected(MenuBuilder menu, MenuItem item) {
   1118             if (mCallback != null) {
   1119                 return mCallback.onActionItemClicked(this, item);
   1120             } else {
   1121                 return false;
   1122             }
   1123         }
   1124 
   1125         public void onCloseMenu(MenuBuilder menu, boolean allMenusAreClosing) {
   1126         }
   1127 
   1128         public boolean onSubMenuSelected(SubMenuBuilder subMenu) {
   1129             if (mCallback == null) {
   1130                 return false;
   1131             }
   1132 
   1133             if (!subMenu.hasVisibleItems()) {
   1134                 return true;
   1135             }
   1136 
   1137             new MenuPopupHelper(getThemedContext(), subMenu).show();
   1138             return true;
   1139         }
   1140 
   1141         public void onCloseSubMenu(SubMenuBuilder menu) {
   1142         }
   1143 
   1144         public void onMenuModeChange(MenuBuilder menu) {
   1145             if (mCallback == null) {
   1146                 return;
   1147             }
   1148             invalidate();
   1149             mContextView.showOverflowMenu();
   1150         }
   1151     }
   1152 
   1153     /**
   1154      * @hide
   1155      */
   1156     public class TabImpl extends ActionBar.Tab {
   1157         private ActionBar.TabListener mCallback;
   1158         private Object mTag;
   1159         private Drawable mIcon;
   1160         private CharSequence mText;
   1161         private CharSequence mContentDesc;
   1162         private int mPosition = -1;
   1163         private View mCustomView;
   1164 
   1165         @Override
   1166         public Object getTag() {
   1167             return mTag;
   1168         }
   1169 
   1170         @Override
   1171         public Tab setTag(Object tag) {
   1172             mTag = tag;
   1173             return this;
   1174         }
   1175 
   1176         public ActionBar.TabListener getCallback() {
   1177             return mCallback;
   1178         }
   1179 
   1180         @Override
   1181         public Tab setTabListener(ActionBar.TabListener callback) {
   1182             mCallback = callback;
   1183             return this;
   1184         }
   1185 
   1186         @Override
   1187         public View getCustomView() {
   1188             return mCustomView;
   1189         }
   1190 
   1191         @Override
   1192         public Tab setCustomView(View view) {
   1193             mCustomView = view;
   1194             if (mPosition >= 0) {
   1195                 mTabScrollView.updateTab(mPosition);
   1196             }
   1197             return this;
   1198         }
   1199 
   1200         @Override
   1201         public Tab setCustomView(int layoutResId) {
   1202             return setCustomView(LayoutInflater.from(getThemedContext())
   1203                     .inflate(layoutResId, null));
   1204         }
   1205 
   1206         @Override
   1207         public Drawable getIcon() {
   1208             return mIcon;
   1209         }
   1210 
   1211         @Override
   1212         public int getPosition() {
   1213             return mPosition;
   1214         }
   1215 
   1216         public void setPosition(int position) {
   1217             mPosition = position;
   1218         }
   1219 
   1220         @Override
   1221         public CharSequence getText() {
   1222             return mText;
   1223         }
   1224 
   1225         @Override
   1226         public Tab setIcon(Drawable icon) {
   1227             mIcon = icon;
   1228             if (mPosition >= 0) {
   1229                 mTabScrollView.updateTab(mPosition);
   1230             }
   1231             return this;
   1232         }
   1233 
   1234         @Override
   1235         public Tab setIcon(int resId) {
   1236             return setIcon(mContext.getDrawable(resId));
   1237         }
   1238 
   1239         @Override
   1240         public Tab setText(CharSequence text) {
   1241             mText = text;
   1242             if (mPosition >= 0) {
   1243                 mTabScrollView.updateTab(mPosition);
   1244             }
   1245             return this;
   1246         }
   1247 
   1248         @Override
   1249         public Tab setText(int resId) {
   1250             return setText(mContext.getResources().getText(resId));
   1251         }
   1252 
   1253         @Override
   1254         public void select() {
   1255             selectTab(this);
   1256         }
   1257 
   1258         @Override
   1259         public Tab setContentDescription(int resId) {
   1260             return setContentDescription(mContext.getResources().getText(resId));
   1261         }
   1262 
   1263         @Override
   1264         public Tab setContentDescription(CharSequence contentDesc) {
   1265             mContentDesc = contentDesc;
   1266             if (mPosition >= 0) {
   1267                 mTabScrollView.updateTab(mPosition);
   1268             }
   1269             return this;
   1270         }
   1271 
   1272         @Override
   1273         public CharSequence getContentDescription() {
   1274             return mContentDesc;
   1275         }
   1276     }
   1277 
   1278     @Override
   1279     public void setCustomView(View view) {
   1280         mDecorToolbar.setCustomView(view);
   1281     }
   1282 
   1283     @Override
   1284     public void setCustomView(View view, LayoutParams layoutParams) {
   1285         view.setLayoutParams(layoutParams);
   1286         mDecorToolbar.setCustomView(view);
   1287     }
   1288 
   1289     @Override
   1290     public void setListNavigationCallbacks(SpinnerAdapter adapter, OnNavigationListener callback) {
   1291         mDecorToolbar.setDropdownParams(adapter, new NavItemSelectedListener(callback));
   1292     }
   1293 
   1294     @Override
   1295     public int getSelectedNavigationIndex() {
   1296         switch (mDecorToolbar.getNavigationMode()) {
   1297             case NAVIGATION_MODE_TABS:
   1298                 return mSelectedTab != null ? mSelectedTab.getPosition() : -1;
   1299             case NAVIGATION_MODE_LIST:
   1300                 return mDecorToolbar.getDropdownSelectedPosition();
   1301             default:
   1302                 return -1;
   1303         }
   1304     }
   1305 
   1306     @Override
   1307     public int getNavigationItemCount() {
   1308         switch (mDecorToolbar.getNavigationMode()) {
   1309             case NAVIGATION_MODE_TABS:
   1310                 return mTabs.size();
   1311             case NAVIGATION_MODE_LIST:
   1312                 return mDecorToolbar.getDropdownItemCount();
   1313             default:
   1314                 return 0;
   1315         }
   1316     }
   1317 
   1318     @Override
   1319     public int getTabCount() {
   1320         return mTabs.size();
   1321     }
   1322 
   1323     @Override
   1324     public void setNavigationMode(int mode) {
   1325         final int oldMode = mDecorToolbar.getNavigationMode();
   1326         switch (oldMode) {
   1327             case NAVIGATION_MODE_TABS:
   1328                 mSavedTabPosition = getSelectedNavigationIndex();
   1329                 selectTab(null);
   1330                 mTabScrollView.setVisibility(View.GONE);
   1331                 break;
   1332         }
   1333         if (oldMode != mode && !mHasEmbeddedTabs) {
   1334             if (mOverlayLayout != null) {
   1335                 mOverlayLayout.requestFitSystemWindows();
   1336             }
   1337         }
   1338         mDecorToolbar.setNavigationMode(mode);
   1339         switch (mode) {
   1340             case NAVIGATION_MODE_TABS:
   1341                 ensureTabsExist();
   1342                 mTabScrollView.setVisibility(View.VISIBLE);
   1343                 if (mSavedTabPosition != INVALID_POSITION) {
   1344                     setSelectedNavigationItem(mSavedTabPosition);
   1345                     mSavedTabPosition = INVALID_POSITION;
   1346                 }
   1347                 break;
   1348         }
   1349         mDecorToolbar.setCollapsible(mode == NAVIGATION_MODE_TABS && !mHasEmbeddedTabs);
   1350         mOverlayLayout.setHasNonEmbeddedTabs(mode == NAVIGATION_MODE_TABS && !mHasEmbeddedTabs);
   1351     }
   1352 
   1353     @Override
   1354     public Tab getTabAt(int index) {
   1355         return mTabs.get(index);
   1356     }
   1357 
   1358 
   1359     @Override
   1360     public void setIcon(int resId) {
   1361         mDecorToolbar.setIcon(resId);
   1362     }
   1363 
   1364     @Override
   1365     public void setIcon(Drawable icon) {
   1366         mDecorToolbar.setIcon(icon);
   1367     }
   1368 
   1369     public boolean hasIcon() {
   1370         return mDecorToolbar.hasIcon();
   1371     }
   1372 
   1373     @Override
   1374     public void setLogo(int resId) {
   1375         mDecorToolbar.setLogo(resId);
   1376     }
   1377 
   1378     @Override
   1379     public void setLogo(Drawable logo) {
   1380         mDecorToolbar.setLogo(logo);
   1381     }
   1382 
   1383     public boolean hasLogo() {
   1384         return mDecorToolbar.hasLogo();
   1385     }
   1386 
   1387     public void setDefaultDisplayHomeAsUpEnabled(boolean enable) {
   1388         if (!mDisplayHomeAsUpSet) {
   1389             setDisplayHomeAsUpEnabled(enable);
   1390         }
   1391     }
   1392 
   1393 }
   1394