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