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