• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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.widget;
18 
19 import android.animation.LayoutTransition;
20 import android.app.ActionBar;
21 import android.content.Context;
22 import android.content.res.Configuration;
23 import android.content.res.TypedArray;
24 import android.graphics.drawable.Drawable;
25 import android.os.Parcel;
26 import android.os.Parcelable;
27 import android.text.Layout;
28 import android.text.TextUtils;
29 import android.util.AttributeSet;
30 import android.view.CollapsibleActionView;
31 import android.view.Gravity;
32 import android.view.LayoutInflater;
33 import android.view.Menu;
34 import android.view.MenuItem;
35 import android.view.MotionEvent;
36 import android.view.View;
37 import android.view.ViewGroup;
38 import android.view.ViewParent;
39 import android.view.Window;
40 import android.view.accessibility.AccessibilityEvent;
41 import android.widget.ActionMenuPresenter;
42 import android.widget.ActionMenuView;
43 import android.widget.AdapterView;
44 import android.widget.FrameLayout;
45 import android.widget.ImageView;
46 import android.widget.LinearLayout;
47 import android.widget.ProgressBar;
48 import android.widget.Spinner;
49 import android.widget.SpinnerAdapter;
50 import android.widget.TextView;
51 import com.android.internal.R;
52 import com.android.internal.transition.ActionBarTransition;
53 import com.android.internal.view.menu.ActionMenuItem;
54 import com.android.internal.view.menu.MenuBuilder;
55 import com.android.internal.view.menu.MenuItemImpl;
56 import com.android.internal.view.menu.MenuPresenter;
57 import com.android.internal.view.menu.MenuView;
58 import com.android.internal.view.menu.SubMenuBuilder;
59 
60 /**
61  * @hide
62  */
63 public class ActionBarView extends AbsActionBarView implements DecorToolbar {
64     private static final String TAG = "ActionBarView";
65 
66     /**
67      * Display options applied by default
68      */
69     public static final int DISPLAY_DEFAULT = 0;
70 
71     /**
72      * Display options that require re-layout as opposed to a simple invalidate
73      */
74     private static final int DISPLAY_RELAYOUT_MASK =
75             ActionBar.DISPLAY_SHOW_HOME |
76             ActionBar.DISPLAY_USE_LOGO |
77             ActionBar.DISPLAY_HOME_AS_UP |
78             ActionBar.DISPLAY_SHOW_CUSTOM |
79             ActionBar.DISPLAY_SHOW_TITLE |
80             ActionBar.DISPLAY_TITLE_MULTIPLE_LINES;
81 
82     private static final int DEFAULT_CUSTOM_GRAVITY = Gravity.START | Gravity.CENTER_VERTICAL;
83 
84     private int mNavigationMode;
85     private int mDisplayOptions = -1;
86     private CharSequence mTitle;
87     private CharSequence mSubtitle;
88     private Drawable mIcon;
89     private Drawable mLogo;
90     private CharSequence mHomeDescription;
91     private int mHomeDescriptionRes;
92 
93     private HomeView mHomeLayout;
94     private HomeView mExpandedHomeLayout;
95     private LinearLayout mTitleLayout;
96     private TextView mTitleView;
97     private TextView mSubtitleView;
98     private ViewGroup mUpGoerFive;
99 
100     private Spinner mSpinner;
101     private LinearLayout mListNavLayout;
102     private ScrollingTabContainerView mTabScrollView;
103     private View mCustomNavView;
104     private ProgressBar mProgressView;
105     private ProgressBar mIndeterminateProgressView;
106 
107     private int mProgressBarPadding;
108     private int mItemPadding;
109 
110     private final int mTitleStyleRes;
111     private final int mSubtitleStyleRes;
112     private final int mProgressStyle;
113     private final int mIndeterminateProgressStyle;
114 
115     private boolean mUserTitle;
116     private boolean mIncludeTabs;
117     private boolean mIsCollapsible;
118     private boolean mWasHomeEnabled; // Was it enabled before action view expansion?
119 
120     private MenuBuilder mOptionsMenu;
121     private boolean mMenuPrepared;
122 
123     private ActionBarContextView mContextView;
124 
125     private ActionMenuItem mLogoNavItem;
126 
127     private SpinnerAdapter mSpinnerAdapter;
128     private AdapterView.OnItemSelectedListener mNavItemSelectedListener;
129 
130     private Runnable mTabSelector;
131 
132     private ExpandedActionViewMenuPresenter mExpandedMenuPresenter;
133     View mExpandedActionView;
134     private int mDefaultUpDescription = R.string.action_bar_up_description;
135 
136     Window.Callback mWindowCallback;
137 
138     private final OnClickListener mExpandedActionViewUpListener = new OnClickListener() {
139         @Override
140         public void onClick(View v) {
141             final MenuItemImpl item = mExpandedMenuPresenter.mCurrentExpandedItem;
142             if (item != null) {
143                 item.collapseActionView();
144             }
145         }
146     };
147 
148     private final OnClickListener mUpClickListener = new OnClickListener() {
149         public void onClick(View v) {
150             if (mMenuPrepared) {
151                 // Only invoke the window callback if the options menu has been initialized.
152                 mWindowCallback.onMenuItemSelected(Window.FEATURE_OPTIONS_PANEL, mLogoNavItem);
153             }
154         }
155     };
156 
ActionBarView(Context context, AttributeSet attrs)157     public ActionBarView(Context context, AttributeSet attrs) {
158         super(context, attrs);
159 
160         // Background is always provided by the container.
161         setBackgroundResource(0);
162 
163         TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.ActionBar,
164                 com.android.internal.R.attr.actionBarStyle, 0);
165 
166         mNavigationMode = a.getInt(R.styleable.ActionBar_navigationMode,
167                 ActionBar.NAVIGATION_MODE_STANDARD);
168         mTitle = a.getText(R.styleable.ActionBar_title);
169         mSubtitle = a.getText(R.styleable.ActionBar_subtitle);
170         mLogo = a.getDrawable(R.styleable.ActionBar_logo);
171         mIcon = a.getDrawable(R.styleable.ActionBar_icon);
172 
173         final LayoutInflater inflater = LayoutInflater.from(context);
174 
175         final int homeResId = a.getResourceId(
176                 com.android.internal.R.styleable.ActionBar_homeLayout,
177                 com.android.internal.R.layout.action_bar_home);
178 
179         mUpGoerFive = (ViewGroup) inflater.inflate(
180                 com.android.internal.R.layout.action_bar_up_container, this, false);
181         mHomeLayout = (HomeView) inflater.inflate(homeResId, mUpGoerFive, false);
182 
183         mExpandedHomeLayout = (HomeView) inflater.inflate(homeResId, mUpGoerFive, false);
184         mExpandedHomeLayout.setShowUp(true);
185         mExpandedHomeLayout.setOnClickListener(mExpandedActionViewUpListener);
186         mExpandedHomeLayout.setContentDescription(getResources().getText(
187                 mDefaultUpDescription));
188 
189         // This needs to highlight/be focusable on its own.
190         // TODO: Clean up the handoff between expanded/normal.
191         final Drawable upBackground = mUpGoerFive.getBackground();
192         if (upBackground != null) {
193             mExpandedHomeLayout.setBackground(upBackground.getConstantState().newDrawable());
194         }
195         mExpandedHomeLayout.setEnabled(true);
196         mExpandedHomeLayout.setFocusable(true);
197 
198         mTitleStyleRes = a.getResourceId(R.styleable.ActionBar_titleTextStyle, 0);
199         mSubtitleStyleRes = a.getResourceId(R.styleable.ActionBar_subtitleTextStyle, 0);
200         mProgressStyle = a.getResourceId(R.styleable.ActionBar_progressBarStyle, 0);
201         mIndeterminateProgressStyle = a.getResourceId(
202                 R.styleable.ActionBar_indeterminateProgressStyle, 0);
203 
204         mProgressBarPadding = a.getDimensionPixelOffset(R.styleable.ActionBar_progressBarPadding, 0);
205         mItemPadding = a.getDimensionPixelOffset(R.styleable.ActionBar_itemPadding, 0);
206 
207         setDisplayOptions(a.getInt(R.styleable.ActionBar_displayOptions, DISPLAY_DEFAULT));
208 
209         final int customNavId = a.getResourceId(R.styleable.ActionBar_customNavigationLayout, 0);
210         if (customNavId != 0) {
211             mCustomNavView = (View) inflater.inflate(customNavId, this, false);
212             mNavigationMode = ActionBar.NAVIGATION_MODE_STANDARD;
213             setDisplayOptions(mDisplayOptions | ActionBar.DISPLAY_SHOW_CUSTOM);
214         }
215 
216         mContentHeight = a.getLayoutDimension(R.styleable.ActionBar_height, 0);
217 
218         a.recycle();
219 
220         mLogoNavItem = new ActionMenuItem(context, 0, android.R.id.home, 0, 0, mTitle);
221 
222         mUpGoerFive.setOnClickListener(mUpClickListener);
223         mUpGoerFive.setClickable(true);
224         mUpGoerFive.setFocusable(true);
225 
226         if (getImportantForAccessibility() == View.IMPORTANT_FOR_ACCESSIBILITY_AUTO) {
227             setImportantForAccessibility(View.IMPORTANT_FOR_ACCESSIBILITY_YES);
228         }
229     }
230 
231     @Override
onConfigurationChanged(Configuration newConfig)232     protected void onConfigurationChanged(Configuration newConfig) {
233         super.onConfigurationChanged(newConfig);
234 
235         mTitleView = null;
236         mSubtitleView = null;
237         if (mTitleLayout != null && mTitleLayout.getParent() == mUpGoerFive) {
238             mUpGoerFive.removeView(mTitleLayout);
239         }
240         mTitleLayout = null;
241         if ((mDisplayOptions & ActionBar.DISPLAY_SHOW_TITLE) != 0) {
242             initTitle();
243         }
244 
245         if (mHomeDescriptionRes != 0) {
246             setNavigationContentDescription(mHomeDescriptionRes);
247         }
248 
249         if (mTabScrollView != null && mIncludeTabs) {
250             ViewGroup.LayoutParams lp = mTabScrollView.getLayoutParams();
251             if (lp != null) {
252                 lp.width = LayoutParams.WRAP_CONTENT;
253                 lp.height = LayoutParams.MATCH_PARENT;
254             }
255             mTabScrollView.setAllowCollapse(true);
256         }
257     }
258 
259     /**
260      * Set the window callback used to invoke menu items; used for dispatching home button presses.
261      * @param cb Window callback to dispatch to
262      */
setWindowCallback(Window.Callback cb)263     public void setWindowCallback(Window.Callback cb) {
264         mWindowCallback = cb;
265     }
266 
267     @Override
onDetachedFromWindow()268     public void onDetachedFromWindow() {
269         super.onDetachedFromWindow();
270         removeCallbacks(mTabSelector);
271         if (mActionMenuPresenter != null) {
272             mActionMenuPresenter.hideOverflowMenu();
273             mActionMenuPresenter.hideSubMenus();
274         }
275     }
276 
277     @Override
shouldDelayChildPressedState()278     public boolean shouldDelayChildPressedState() {
279         return false;
280     }
281 
initProgress()282     public void initProgress() {
283         mProgressView = new ProgressBar(mContext, null, 0, mProgressStyle);
284         mProgressView.setId(R.id.progress_horizontal);
285         mProgressView.setMax(10000);
286         mProgressView.setVisibility(GONE);
287         addView(mProgressView);
288     }
289 
initIndeterminateProgress()290     public void initIndeterminateProgress() {
291         mIndeterminateProgressView = new ProgressBar(mContext, null, 0,
292                 mIndeterminateProgressStyle);
293         mIndeterminateProgressView.setId(R.id.progress_circular);
294         mIndeterminateProgressView.setVisibility(GONE);
295         addView(mIndeterminateProgressView);
296     }
297 
298     @Override
setSplitToolbar(boolean splitActionBar)299     public void setSplitToolbar(boolean splitActionBar) {
300         if (mSplitActionBar != splitActionBar) {
301             if (mMenuView != null) {
302                 final ViewGroup oldParent = (ViewGroup) mMenuView.getParent();
303                 if (oldParent != null) {
304                     oldParent.removeView(mMenuView);
305                 }
306                 if (splitActionBar) {
307                     if (mSplitView != null) {
308                         mSplitView.addView(mMenuView);
309                     }
310                     mMenuView.getLayoutParams().width = LayoutParams.MATCH_PARENT;
311                 } else {
312                     addView(mMenuView);
313                     mMenuView.getLayoutParams().width = LayoutParams.WRAP_CONTENT;
314                 }
315                 mMenuView.requestLayout();
316             }
317             if (mSplitView != null) {
318                 mSplitView.setVisibility(splitActionBar ? VISIBLE : GONE);
319             }
320 
321             if (mActionMenuPresenter != null) {
322                 if (!splitActionBar) {
323                     mActionMenuPresenter.setExpandedActionViewsExclusive(
324                             getResources().getBoolean(
325                                     com.android.internal.R.bool.action_bar_expanded_action_views_exclusive));
326                 } else {
327                     mActionMenuPresenter.setExpandedActionViewsExclusive(false);
328                     // Allow full screen width in split mode.
329                     mActionMenuPresenter.setWidthLimit(
330                             getContext().getResources().getDisplayMetrics().widthPixels, true);
331                     // No limit to the item count; use whatever will fit.
332                     mActionMenuPresenter.setItemLimit(Integer.MAX_VALUE);
333                 }
334             }
335             super.setSplitToolbar(splitActionBar);
336         }
337     }
338 
isSplit()339     public boolean isSplit() {
340         return mSplitActionBar;
341     }
342 
canSplit()343     public boolean canSplit() {
344         return true;
345     }
346 
hasEmbeddedTabs()347     public boolean hasEmbeddedTabs() {
348         return mIncludeTabs;
349     }
350 
351     @Override
setEmbeddedTabView(ScrollingTabContainerView tabs)352     public void setEmbeddedTabView(ScrollingTabContainerView tabs) {
353         if (mTabScrollView != null) {
354             removeView(mTabScrollView);
355         }
356         mTabScrollView = tabs;
357         mIncludeTabs = tabs != null;
358         if (mIncludeTabs && mNavigationMode == ActionBar.NAVIGATION_MODE_TABS) {
359             addView(mTabScrollView);
360             ViewGroup.LayoutParams lp = mTabScrollView.getLayoutParams();
361             lp.width = LayoutParams.WRAP_CONTENT;
362             lp.height = LayoutParams.MATCH_PARENT;
363             tabs.setAllowCollapse(true);
364         }
365     }
366 
setMenuPrepared()367     public void setMenuPrepared() {
368         mMenuPrepared = true;
369     }
370 
setMenu(Menu menu, MenuPresenter.Callback cb)371     public void setMenu(Menu menu, MenuPresenter.Callback cb) {
372         if (menu == mOptionsMenu) return;
373 
374         if (mOptionsMenu != null) {
375             mOptionsMenu.removeMenuPresenter(mActionMenuPresenter);
376             mOptionsMenu.removeMenuPresenter(mExpandedMenuPresenter);
377         }
378 
379         MenuBuilder builder = (MenuBuilder) menu;
380         mOptionsMenu = builder;
381         if (mMenuView != null) {
382             final ViewGroup oldParent = (ViewGroup) mMenuView.getParent();
383             if (oldParent != null) {
384                 oldParent.removeView(mMenuView);
385             }
386         }
387         if (mActionMenuPresenter == null) {
388             mActionMenuPresenter = new ActionMenuPresenter(mContext);
389             mActionMenuPresenter.setCallback(cb);
390             mActionMenuPresenter.setId(com.android.internal.R.id.action_menu_presenter);
391             mExpandedMenuPresenter = new ExpandedActionViewMenuPresenter();
392         }
393 
394         ActionMenuView menuView;
395         final LayoutParams layoutParams = new LayoutParams(LayoutParams.WRAP_CONTENT,
396                 LayoutParams.MATCH_PARENT);
397         if (!mSplitActionBar) {
398             mActionMenuPresenter.setExpandedActionViewsExclusive(
399                     getResources().getBoolean(
400                     com.android.internal.R.bool.action_bar_expanded_action_views_exclusive));
401             configPresenters(builder);
402             menuView = (ActionMenuView) mActionMenuPresenter.getMenuView(this);
403             final ViewGroup oldParent = (ViewGroup) menuView.getParent();
404             if (oldParent != null && oldParent != this) {
405                 oldParent.removeView(menuView);
406             }
407             addView(menuView, layoutParams);
408         } else {
409             mActionMenuPresenter.setExpandedActionViewsExclusive(false);
410             // Allow full screen width in split mode.
411             mActionMenuPresenter.setWidthLimit(
412                     getContext().getResources().getDisplayMetrics().widthPixels, true);
413             // No limit to the item count; use whatever will fit.
414             mActionMenuPresenter.setItemLimit(Integer.MAX_VALUE);
415             // Span the whole width
416             layoutParams.width = LayoutParams.MATCH_PARENT;
417             layoutParams.height = LayoutParams.WRAP_CONTENT;
418             configPresenters(builder);
419             menuView = (ActionMenuView) mActionMenuPresenter.getMenuView(this);
420             if (mSplitView != null) {
421                 final ViewGroup oldParent = (ViewGroup) menuView.getParent();
422                 if (oldParent != null && oldParent != mSplitView) {
423                     oldParent.removeView(menuView);
424                 }
425                 menuView.setVisibility(getAnimatedVisibility());
426                 mSplitView.addView(menuView, layoutParams);
427             } else {
428                 // We'll add this later if we missed it this time.
429                 menuView.setLayoutParams(layoutParams);
430             }
431         }
432         mMenuView = menuView;
433     }
434 
configPresenters(MenuBuilder builder)435     private void configPresenters(MenuBuilder builder) {
436         if (builder != null) {
437             builder.addMenuPresenter(mActionMenuPresenter, mPopupContext);
438             builder.addMenuPresenter(mExpandedMenuPresenter, mPopupContext);
439         } else {
440             mActionMenuPresenter.initForMenu(mPopupContext, null);
441             mExpandedMenuPresenter.initForMenu(mPopupContext, null);
442             mActionMenuPresenter.updateMenuView(true);
443             mExpandedMenuPresenter.updateMenuView(true);
444         }
445     }
446 
hasExpandedActionView()447     public boolean hasExpandedActionView() {
448         return mExpandedMenuPresenter != null &&
449                 mExpandedMenuPresenter.mCurrentExpandedItem != null;
450     }
451 
collapseActionView()452     public void collapseActionView() {
453         final MenuItemImpl item = mExpandedMenuPresenter == null ? null :
454                 mExpandedMenuPresenter.mCurrentExpandedItem;
455         if (item != null) {
456             item.collapseActionView();
457         }
458     }
459 
setCustomView(View view)460     public void setCustomView(View view) {
461         final boolean showCustom = (mDisplayOptions & ActionBar.DISPLAY_SHOW_CUSTOM) != 0;
462         if (showCustom) {
463             ActionBarTransition.beginDelayedTransition(this);
464         }
465         if (mCustomNavView != null && showCustom) {
466             removeView(mCustomNavView);
467         }
468         mCustomNavView = view;
469         if (mCustomNavView != null && showCustom) {
470             addView(mCustomNavView);
471         }
472     }
473 
getTitle()474     public CharSequence getTitle() {
475         return mTitle;
476     }
477 
478     /**
479      * Set the action bar title. This will always replace or override window titles.
480      * @param title Title to set
481      *
482      * @see #setWindowTitle(CharSequence)
483      */
setTitle(CharSequence title)484     public void setTitle(CharSequence title) {
485         mUserTitle = true;
486         setTitleImpl(title);
487     }
488 
489     /**
490      * Set the window title. A window title will always be replaced or overridden by a user title.
491      * @param title Title to set
492      *
493      * @see #setTitle(CharSequence)
494      */
setWindowTitle(CharSequence title)495     public void setWindowTitle(CharSequence title) {
496         if (!mUserTitle) {
497             setTitleImpl(title);
498         }
499     }
500 
setTitleImpl(CharSequence title)501     private void setTitleImpl(CharSequence title) {
502         ActionBarTransition.beginDelayedTransition(this);
503         mTitle = title;
504         if (mTitleView != null) {
505             mTitleView.setText(title);
506             final boolean visible = mExpandedActionView == null &&
507                     (mDisplayOptions & ActionBar.DISPLAY_SHOW_TITLE) != 0 &&
508                     (!TextUtils.isEmpty(mTitle) || !TextUtils.isEmpty(mSubtitle));
509             mTitleLayout.setVisibility(visible ? VISIBLE : GONE);
510         }
511         if (mLogoNavItem != null) {
512             mLogoNavItem.setTitle(title);
513         }
514         updateHomeAccessibility(mUpGoerFive.isEnabled());
515     }
516 
getSubtitle()517     public CharSequence getSubtitle() {
518         return mSubtitle;
519     }
520 
setSubtitle(CharSequence subtitle)521     public void setSubtitle(CharSequence subtitle) {
522         ActionBarTransition.beginDelayedTransition(this);
523         mSubtitle = subtitle;
524         if (mSubtitleView != null) {
525             mSubtitleView.setText(subtitle);
526             mSubtitleView.setVisibility(subtitle != null ? VISIBLE : GONE);
527             final boolean visible = mExpandedActionView == null &&
528                     (mDisplayOptions & ActionBar.DISPLAY_SHOW_TITLE) != 0 &&
529                     (!TextUtils.isEmpty(mTitle) || !TextUtils.isEmpty(mSubtitle));
530             mTitleLayout.setVisibility(visible ? VISIBLE : GONE);
531         }
532         updateHomeAccessibility(mUpGoerFive.isEnabled());
533     }
534 
setHomeButtonEnabled(boolean enable)535     public void setHomeButtonEnabled(boolean enable) {
536         setHomeButtonEnabled(enable, true);
537     }
538 
setHomeButtonEnabled(boolean enable, boolean recordState)539     private void setHomeButtonEnabled(boolean enable, boolean recordState) {
540         if (recordState) {
541             mWasHomeEnabled = enable;
542         }
543 
544         if (mExpandedActionView != null) {
545             // There's an action view currently showing and we want to keep the state
546             // configured for the action view at the moment. If we needed to record the
547             // new state for later we will have done so above.
548             return;
549         }
550 
551         mUpGoerFive.setEnabled(enable);
552         mUpGoerFive.setFocusable(enable);
553         // Make sure the home button has an accurate content description for accessibility.
554         updateHomeAccessibility(enable);
555     }
556 
updateHomeAccessibility(boolean homeEnabled)557     private void updateHomeAccessibility(boolean homeEnabled) {
558         if (!homeEnabled) {
559             mUpGoerFive.setContentDescription(null);
560             mUpGoerFive.setImportantForAccessibility(IMPORTANT_FOR_ACCESSIBILITY_NO);
561         } else {
562             mUpGoerFive.setImportantForAccessibility(IMPORTANT_FOR_ACCESSIBILITY_AUTO);
563             mUpGoerFive.setContentDescription(buildHomeContentDescription());
564         }
565     }
566 
567     /**
568      * Compose a content description for the Home/Up affordance.
569      *
570      * <p>As this encompasses the icon/logo, title and subtitle all in one, we need
571      * a description for the whole wad of stuff that can be localized properly.</p>
572      */
buildHomeContentDescription()573     private CharSequence buildHomeContentDescription() {
574         final CharSequence homeDesc;
575         if (mHomeDescription != null) {
576             homeDesc = mHomeDescription;
577         } else {
578             if ((mDisplayOptions & ActionBar.DISPLAY_HOME_AS_UP) != 0) {
579                 homeDesc = mContext.getResources().getText(mDefaultUpDescription);
580             } else {
581                 homeDesc = mContext.getResources().getText(R.string.action_bar_home_description);
582             }
583         }
584 
585         final CharSequence title = getTitle();
586         final CharSequence subtitle = getSubtitle();
587         if (!TextUtils.isEmpty(title)) {
588             final String result;
589             if (!TextUtils.isEmpty(subtitle)) {
590                 result = getResources().getString(
591                         R.string.action_bar_home_subtitle_description_format,
592                         title, subtitle, homeDesc);
593             } else {
594                 result = getResources().getString(R.string.action_bar_home_description_format,
595                         title, homeDesc);
596             }
597             return result;
598         }
599         return homeDesc;
600     }
601 
setDisplayOptions(int options)602     public void setDisplayOptions(int options) {
603         final int flagsChanged = mDisplayOptions == -1 ? -1 : options ^ mDisplayOptions;
604         mDisplayOptions = options;
605 
606         if ((flagsChanged & DISPLAY_RELAYOUT_MASK) != 0) {
607             ActionBarTransition.beginDelayedTransition(this);
608 
609             if ((flagsChanged & ActionBar.DISPLAY_HOME_AS_UP) != 0) {
610                 final boolean setUp = (options & ActionBar.DISPLAY_HOME_AS_UP) != 0;
611                 mHomeLayout.setShowUp(setUp);
612 
613                 // Showing home as up implicitly enables interaction with it.
614                 // In honeycomb it was always enabled, so make this transition
615                 // a bit easier for developers in the common case.
616                 // (It would be silly to show it as up without responding to it.)
617                 if (setUp) {
618                     setHomeButtonEnabled(true);
619                 }
620             }
621 
622             if ((flagsChanged & ActionBar.DISPLAY_USE_LOGO) != 0) {
623                 final boolean logoVis = mLogo != null && (options & ActionBar.DISPLAY_USE_LOGO) != 0;
624                 mHomeLayout.setIcon(logoVis ? mLogo : mIcon);
625             }
626 
627             if ((flagsChanged & ActionBar.DISPLAY_SHOW_TITLE) != 0) {
628                 if ((options & ActionBar.DISPLAY_SHOW_TITLE) != 0) {
629                     initTitle();
630                 } else {
631                     mUpGoerFive.removeView(mTitleLayout);
632                 }
633             }
634 
635             final boolean showHome = (options & ActionBar.DISPLAY_SHOW_HOME) != 0;
636             final boolean homeAsUp = (mDisplayOptions & ActionBar.DISPLAY_HOME_AS_UP) != 0;
637             final boolean titleUp = !showHome && homeAsUp;
638             mHomeLayout.setShowIcon(showHome);
639 
640             final int homeVis = (showHome || titleUp) && mExpandedActionView == null ?
641                     VISIBLE : GONE;
642             mHomeLayout.setVisibility(homeVis);
643 
644             if ((flagsChanged & ActionBar.DISPLAY_SHOW_CUSTOM) != 0 && mCustomNavView != null) {
645                 if ((options & ActionBar.DISPLAY_SHOW_CUSTOM) != 0) {
646                     addView(mCustomNavView);
647                 } else {
648                     removeView(mCustomNavView);
649                 }
650             }
651 
652             if (mTitleLayout != null &&
653                     (flagsChanged & ActionBar.DISPLAY_TITLE_MULTIPLE_LINES) != 0) {
654                 if ((options & ActionBar.DISPLAY_TITLE_MULTIPLE_LINES) != 0) {
655                     mTitleView.setSingleLine(false);
656                     mTitleView.setMaxLines(2);
657                 } else {
658                     mTitleView.setMaxLines(1);
659                     mTitleView.setSingleLine(true);
660                 }
661             }
662 
663             requestLayout();
664         } else {
665             invalidate();
666         }
667 
668         // Make sure the home button has an accurate content description for accessibility.
669         updateHomeAccessibility(mUpGoerFive.isEnabled());
670     }
671 
setIcon(Drawable icon)672     public void setIcon(Drawable icon) {
673         mIcon = icon;
674         if (icon != null &&
675                 ((mDisplayOptions & ActionBar.DISPLAY_USE_LOGO) == 0 || mLogo == null)) {
676             mHomeLayout.setIcon(icon);
677         }
678         if (mExpandedActionView != null) {
679             mExpandedHomeLayout.setIcon(mIcon.getConstantState().newDrawable(getResources()));
680         }
681     }
682 
setIcon(int resId)683     public void setIcon(int resId) {
684         setIcon(resId != 0 ? mContext.getDrawable(resId) : null);
685     }
686 
hasIcon()687     public boolean hasIcon() {
688         return mIcon != null;
689     }
690 
setLogo(Drawable logo)691     public void setLogo(Drawable logo) {
692         mLogo = logo;
693         if (logo != null && (mDisplayOptions & ActionBar.DISPLAY_USE_LOGO) != 0) {
694             mHomeLayout.setIcon(logo);
695         }
696     }
697 
setLogo(int resId)698     public void setLogo(int resId) {
699         setLogo(resId != 0 ? mContext.getDrawable(resId) : null);
700     }
701 
hasLogo()702     public boolean hasLogo() {
703         return mLogo != null;
704     }
705 
setNavigationMode(int mode)706     public void setNavigationMode(int mode) {
707         final int oldMode = mNavigationMode;
708         if (mode != oldMode) {
709             ActionBarTransition.beginDelayedTransition(this);
710             switch (oldMode) {
711             case ActionBar.NAVIGATION_MODE_LIST:
712                 if (mListNavLayout != null) {
713                     removeView(mListNavLayout);
714                 }
715                 break;
716             case ActionBar.NAVIGATION_MODE_TABS:
717                 if (mTabScrollView != null && mIncludeTabs) {
718                     removeView(mTabScrollView);
719                 }
720             }
721 
722             switch (mode) {
723             case ActionBar.NAVIGATION_MODE_LIST:
724                 if (mSpinner == null) {
725                     mSpinner = new Spinner(mContext, null,
726                             com.android.internal.R.attr.actionDropDownStyle);
727                     mSpinner.setId(com.android.internal.R.id.action_bar_spinner);
728                     mListNavLayout = new LinearLayout(mContext, null,
729                             com.android.internal.R.attr.actionBarTabBarStyle);
730                     LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(
731                             LayoutParams.WRAP_CONTENT, LayoutParams.MATCH_PARENT);
732                     params.gravity = Gravity.CENTER;
733                     mListNavLayout.addView(mSpinner, params);
734                 }
735                 if (mSpinner.getAdapter() != mSpinnerAdapter) {
736                     mSpinner.setAdapter(mSpinnerAdapter);
737                 }
738                 mSpinner.setOnItemSelectedListener(mNavItemSelectedListener);
739                 addView(mListNavLayout);
740                 break;
741             case ActionBar.NAVIGATION_MODE_TABS:
742                 if (mTabScrollView != null && mIncludeTabs) {
743                     addView(mTabScrollView);
744                 }
745                 break;
746             }
747             mNavigationMode = mode;
748             requestLayout();
749         }
750     }
751 
setDropdownParams(SpinnerAdapter adapter, AdapterView.OnItemSelectedListener l)752     public void setDropdownParams(SpinnerAdapter adapter, AdapterView.OnItemSelectedListener l) {
753         mSpinnerAdapter = adapter;
754         mNavItemSelectedListener = l;
755         if (mSpinner != null) {
756             mSpinner.setAdapter(adapter);
757             mSpinner.setOnItemSelectedListener(l);
758         }
759     }
760 
getDropdownItemCount()761     public int getDropdownItemCount() {
762         return mSpinnerAdapter != null ? mSpinnerAdapter.getCount() : 0;
763     }
764 
setDropdownSelectedPosition(int position)765     public void setDropdownSelectedPosition(int position) {
766         mSpinner.setSelection(position);
767     }
768 
getDropdownSelectedPosition()769     public int getDropdownSelectedPosition() {
770         return mSpinner.getSelectedItemPosition();
771     }
772 
getCustomView()773     public View getCustomView() {
774         return mCustomNavView;
775     }
776 
getNavigationMode()777     public int getNavigationMode() {
778         return mNavigationMode;
779     }
780 
getDisplayOptions()781     public int getDisplayOptions() {
782         return mDisplayOptions;
783     }
784 
785     @Override
getViewGroup()786     public ViewGroup getViewGroup() {
787         return this;
788     }
789 
790     @Override
generateDefaultLayoutParams()791     protected ViewGroup.LayoutParams generateDefaultLayoutParams() {
792         // Used by custom nav views if they don't supply layout params. Everything else
793         // added to an ActionBarView should have them already.
794         return new ActionBar.LayoutParams(DEFAULT_CUSTOM_GRAVITY);
795     }
796 
797     @Override
onFinishInflate()798     protected void onFinishInflate() {
799         super.onFinishInflate();
800 
801         mUpGoerFive.addView(mHomeLayout, 0);
802         addView(mUpGoerFive);
803 
804         if (mCustomNavView != null && (mDisplayOptions & ActionBar.DISPLAY_SHOW_CUSTOM) != 0) {
805             final ViewParent parent = mCustomNavView.getParent();
806             if (parent != this) {
807                 if (parent instanceof ViewGroup) {
808                     ((ViewGroup) parent).removeView(mCustomNavView);
809                 }
810                 addView(mCustomNavView);
811             }
812         }
813     }
814 
initTitle()815     private void initTitle() {
816         if (mTitleLayout == null) {
817             LayoutInflater inflater = LayoutInflater.from(getContext());
818             mTitleLayout = (LinearLayout) inflater.inflate(R.layout.action_bar_title_item,
819                     this, false);
820             mTitleView = (TextView) mTitleLayout.findViewById(R.id.action_bar_title);
821             mSubtitleView = (TextView) mTitleLayout.findViewById(R.id.action_bar_subtitle);
822 
823             if (mTitleStyleRes != 0) {
824                 mTitleView.setTextAppearance(mContext, mTitleStyleRes);
825             }
826             if (mTitle != null) {
827                 mTitleView.setText(mTitle);
828             }
829 
830             if (mSubtitleStyleRes != 0) {
831                 mSubtitleView.setTextAppearance(mContext, mSubtitleStyleRes);
832             }
833             if (mSubtitle != null) {
834                 mSubtitleView.setText(mSubtitle);
835                 mSubtitleView.setVisibility(VISIBLE);
836             }
837         }
838 
839         ActionBarTransition.beginDelayedTransition(this);
840         mUpGoerFive.addView(mTitleLayout);
841         if (mExpandedActionView != null ||
842                 (TextUtils.isEmpty(mTitle) && TextUtils.isEmpty(mSubtitle))) {
843             // Don't show while in expanded mode or with empty text
844             mTitleLayout.setVisibility(GONE);
845         } else {
846             mTitleLayout.setVisibility(VISIBLE);
847         }
848     }
849 
setContextView(ActionBarContextView view)850     public void setContextView(ActionBarContextView view) {
851         mContextView = view;
852     }
853 
setCollapsible(boolean collapsible)854     public void setCollapsible(boolean collapsible) {
855         mIsCollapsible = collapsible;
856     }
857 
858     /**
859      * @return True if any characters in the title were truncated
860      */
isTitleTruncated()861     public boolean isTitleTruncated() {
862         if (mTitleView == null) {
863             return false;
864         }
865 
866         final Layout titleLayout = mTitleView.getLayout();
867         if (titleLayout == null) {
868             return false;
869         }
870 
871         final int lineCount = titleLayout.getLineCount();
872         for (int i = 0; i < lineCount; i++) {
873             if (titleLayout.getEllipsisCount(i) > 0) {
874                 return true;
875             }
876         }
877         return false;
878     }
879 
880     @Override
onMeasure(int widthMeasureSpec, int heightMeasureSpec)881     protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
882         final int childCount = getChildCount();
883         if (mIsCollapsible) {
884             int visibleChildren = 0;
885             for (int i = 0; i < childCount; i++) {
886                 final View child = getChildAt(i);
887                 if (child.getVisibility() != GONE &&
888                         !(child == mMenuView && mMenuView.getChildCount() == 0) &&
889                         child != mUpGoerFive) {
890                     visibleChildren++;
891                 }
892             }
893 
894             final int upChildCount = mUpGoerFive.getChildCount();
895             for (int i = 0; i < upChildCount; i++) {
896                 final View child = mUpGoerFive.getChildAt(i);
897                 if (child.getVisibility() != GONE) {
898                     visibleChildren++;
899                 }
900             }
901 
902             if (visibleChildren == 0) {
903                 // No size for an empty action bar when collapsable.
904                 setMeasuredDimension(0, 0);
905                 return;
906             }
907         }
908 
909         int widthMode = MeasureSpec.getMode(widthMeasureSpec);
910         if (widthMode != MeasureSpec.EXACTLY) {
911             throw new IllegalStateException(getClass().getSimpleName() + " can only be used " +
912                     "with android:layout_width=\"match_parent\" (or fill_parent)");
913         }
914 
915         int heightMode = MeasureSpec.getMode(heightMeasureSpec);
916         if (heightMode != MeasureSpec.AT_MOST) {
917             throw new IllegalStateException(getClass().getSimpleName() + " can only be used " +
918                     "with android:layout_height=\"wrap_content\"");
919         }
920 
921         int contentWidth = MeasureSpec.getSize(widthMeasureSpec);
922 
923         int maxHeight = mContentHeight >= 0 ?
924                 mContentHeight : MeasureSpec.getSize(heightMeasureSpec);
925 
926         final int verticalPadding = getPaddingTop() + getPaddingBottom();
927         final int paddingLeft = getPaddingLeft();
928         final int paddingRight = getPaddingRight();
929         final int height = maxHeight - verticalPadding;
930         final int childSpecHeight = MeasureSpec.makeMeasureSpec(height, MeasureSpec.AT_MOST);
931         final int exactHeightSpec = MeasureSpec.makeMeasureSpec(height, MeasureSpec.EXACTLY);
932 
933         int availableWidth = contentWidth - paddingLeft - paddingRight;
934         int leftOfCenter = availableWidth / 2;
935         int rightOfCenter = leftOfCenter;
936 
937         final boolean showTitle = mTitleLayout != null && mTitleLayout.getVisibility() != GONE &&
938                 (mDisplayOptions & ActionBar.DISPLAY_SHOW_TITLE) != 0;
939 
940         HomeView homeLayout = mExpandedActionView != null ? mExpandedHomeLayout : mHomeLayout;
941 
942         final ViewGroup.LayoutParams homeLp = homeLayout.getLayoutParams();
943         int homeWidthSpec;
944         if (homeLp.width < 0) {
945             homeWidthSpec = MeasureSpec.makeMeasureSpec(availableWidth, MeasureSpec.AT_MOST);
946         } else {
947             homeWidthSpec = MeasureSpec.makeMeasureSpec(homeLp.width, MeasureSpec.EXACTLY);
948         }
949 
950         /*
951          * This is a little weird.
952          * We're only measuring the *home* affordance within the Up container here
953          * on purpose, because we want to give the available space to all other views before
954          * the title text. We'll remeasure the whole up container again later.
955          * We need to measure this container so we know the right offset for the up affordance
956          * no matter what.
957          */
958         homeLayout.measure(homeWidthSpec, exactHeightSpec);
959 
960         int homeWidth = 0;
961         if ((homeLayout.getVisibility() != GONE && homeLayout.getParent() == mUpGoerFive)
962                 || showTitle) {
963             homeWidth = homeLayout.getMeasuredWidth();
964             final int homeOffsetWidth = homeWidth + homeLayout.getStartOffset();
965             availableWidth = Math.max(0, availableWidth - homeOffsetWidth);
966             leftOfCenter = Math.max(0, availableWidth - homeOffsetWidth);
967         }
968 
969         if (mMenuView != null && mMenuView.getParent() == this) {
970             availableWidth = measureChildView(mMenuView, availableWidth, exactHeightSpec, 0);
971             rightOfCenter = Math.max(0, rightOfCenter - mMenuView.getMeasuredWidth());
972         }
973 
974         if (mIndeterminateProgressView != null &&
975                 mIndeterminateProgressView.getVisibility() != GONE) {
976             availableWidth = measureChildView(mIndeterminateProgressView, availableWidth,
977                     childSpecHeight, 0);
978             rightOfCenter = Math.max(0,
979                     rightOfCenter - mIndeterminateProgressView.getMeasuredWidth());
980         }
981 
982         if (mExpandedActionView == null) {
983             switch (mNavigationMode) {
984                 case ActionBar.NAVIGATION_MODE_LIST:
985                     if (mListNavLayout != null) {
986                         final int itemPaddingSize = showTitle ? mItemPadding * 2 : mItemPadding;
987                         availableWidth = Math.max(0, availableWidth - itemPaddingSize);
988                         leftOfCenter = Math.max(0, leftOfCenter - itemPaddingSize);
989                         mListNavLayout.measure(
990                                 MeasureSpec.makeMeasureSpec(availableWidth, MeasureSpec.AT_MOST),
991                                 MeasureSpec.makeMeasureSpec(height, MeasureSpec.EXACTLY));
992                         final int listNavWidth = mListNavLayout.getMeasuredWidth();
993                         availableWidth = Math.max(0, availableWidth - listNavWidth);
994                         leftOfCenter = Math.max(0, leftOfCenter - listNavWidth);
995                     }
996                     break;
997                 case ActionBar.NAVIGATION_MODE_TABS:
998                     if (mTabScrollView != null) {
999                         final int itemPaddingSize = showTitle ? mItemPadding * 2 : mItemPadding;
1000                         availableWidth = Math.max(0, availableWidth - itemPaddingSize);
1001                         leftOfCenter = Math.max(0, leftOfCenter - itemPaddingSize);
1002                         mTabScrollView.measure(
1003                                 MeasureSpec.makeMeasureSpec(availableWidth, MeasureSpec.AT_MOST),
1004                                 MeasureSpec.makeMeasureSpec(height, MeasureSpec.EXACTLY));
1005                         final int tabWidth = mTabScrollView.getMeasuredWidth();
1006                         availableWidth = Math.max(0, availableWidth - tabWidth);
1007                         leftOfCenter = Math.max(0, leftOfCenter - tabWidth);
1008                     }
1009                     break;
1010             }
1011         }
1012 
1013         View customView = null;
1014         if (mExpandedActionView != null) {
1015             customView = mExpandedActionView;
1016         } else if ((mDisplayOptions & ActionBar.DISPLAY_SHOW_CUSTOM) != 0 &&
1017                 mCustomNavView != null) {
1018             customView = mCustomNavView;
1019         }
1020 
1021         if (customView != null) {
1022             final ViewGroup.LayoutParams lp = generateLayoutParams(customView.getLayoutParams());
1023             final ActionBar.LayoutParams ablp = lp instanceof ActionBar.LayoutParams ?
1024                     (ActionBar.LayoutParams) lp : null;
1025 
1026             int horizontalMargin = 0;
1027             int verticalMargin = 0;
1028             if (ablp != null) {
1029                 horizontalMargin = ablp.leftMargin + ablp.rightMargin;
1030                 verticalMargin = ablp.topMargin + ablp.bottomMargin;
1031             }
1032 
1033             // If the action bar is wrapping to its content height, don't allow a custom
1034             // view to MATCH_PARENT.
1035             int customNavHeightMode;
1036             if (mContentHeight <= 0) {
1037                 customNavHeightMode = MeasureSpec.AT_MOST;
1038             } else {
1039                 customNavHeightMode = lp.height != LayoutParams.WRAP_CONTENT ?
1040                         MeasureSpec.EXACTLY : MeasureSpec.AT_MOST;
1041             }
1042             final int customNavHeight = Math.max(0,
1043                     (lp.height >= 0 ? Math.min(lp.height, height) : height) - verticalMargin);
1044 
1045             final int customNavWidthMode = lp.width != LayoutParams.WRAP_CONTENT ?
1046                     MeasureSpec.EXACTLY : MeasureSpec.AT_MOST;
1047             int customNavWidth = Math.max(0,
1048                     (lp.width >= 0 ? Math.min(lp.width, availableWidth) : availableWidth)
1049                     - horizontalMargin);
1050             final int hgrav = (ablp != null ? ablp.gravity : DEFAULT_CUSTOM_GRAVITY) &
1051                     Gravity.HORIZONTAL_GRAVITY_MASK;
1052 
1053             // Centering a custom view is treated specially; we try to center within the whole
1054             // action bar rather than in the available space.
1055             if (hgrav == Gravity.CENTER_HORIZONTAL && lp.width == LayoutParams.MATCH_PARENT) {
1056                 customNavWidth = Math.min(leftOfCenter, rightOfCenter) * 2;
1057             }
1058 
1059             customView.measure(
1060                     MeasureSpec.makeMeasureSpec(customNavWidth, customNavWidthMode),
1061                     MeasureSpec.makeMeasureSpec(customNavHeight, customNavHeightMode));
1062             availableWidth -= horizontalMargin + customView.getMeasuredWidth();
1063         }
1064 
1065         /*
1066          * Measure the whole up container now, allowing for the full home+title sections.
1067          * (This will re-measure the home view.)
1068          */
1069         availableWidth = measureChildView(mUpGoerFive, availableWidth + homeWidth,
1070                 MeasureSpec.makeMeasureSpec(mContentHeight, MeasureSpec.EXACTLY), 0);
1071         if (mTitleLayout != null) {
1072             leftOfCenter = Math.max(0, leftOfCenter - mTitleLayout.getMeasuredWidth());
1073         }
1074 
1075         if (mContentHeight <= 0) {
1076             int measuredHeight = 0;
1077             for (int i = 0; i < childCount; i++) {
1078                 View v = getChildAt(i);
1079                 int paddedViewHeight = v.getMeasuredHeight() + verticalPadding;
1080                 if (paddedViewHeight > measuredHeight) {
1081                     measuredHeight = paddedViewHeight;
1082                 }
1083             }
1084             setMeasuredDimension(contentWidth, measuredHeight);
1085         } else {
1086             setMeasuredDimension(contentWidth, maxHeight);
1087         }
1088 
1089         if (mContextView != null) {
1090             mContextView.setContentHeight(getMeasuredHeight());
1091         }
1092 
1093         if (mProgressView != null && mProgressView.getVisibility() != GONE) {
1094             mProgressView.measure(MeasureSpec.makeMeasureSpec(
1095                     contentWidth - mProgressBarPadding * 2, MeasureSpec.EXACTLY),
1096                     MeasureSpec.makeMeasureSpec(getMeasuredHeight(), MeasureSpec.AT_MOST));
1097         }
1098     }
1099 
1100     @Override
onLayout(boolean changed, int l, int t, int r, int b)1101     protected void onLayout(boolean changed, int l, int t, int r, int b) {
1102         final int contentHeight = b - t - getPaddingTop() - getPaddingBottom();
1103 
1104         if (contentHeight <= 0) {
1105             // Nothing to do if we can't see anything.
1106             return;
1107         }
1108 
1109         final boolean isLayoutRtl = isLayoutRtl();
1110         final int direction = isLayoutRtl ? 1 : -1;
1111         int menuStart = isLayoutRtl ? getPaddingLeft() : r - l - getPaddingRight();
1112         // In LTR mode, we start from left padding and go to the right; in RTL mode, we start
1113         // from the padding right and go to the left (in reverse way)
1114         int x = isLayoutRtl ? r - l - getPaddingRight() : getPaddingLeft();
1115         final int y = getPaddingTop();
1116 
1117         HomeView homeLayout = mExpandedActionView != null ? mExpandedHomeLayout : mHomeLayout;
1118         final boolean showTitle = mTitleLayout != null && mTitleLayout.getVisibility() != GONE &&
1119                 (mDisplayOptions & ActionBar.DISPLAY_SHOW_TITLE) != 0;
1120         int startOffset = 0;
1121         if (homeLayout.getParent() == mUpGoerFive) {
1122             if (homeLayout.getVisibility() != GONE) {
1123                 startOffset = homeLayout.getStartOffset();
1124             } else if (showTitle) {
1125                 startOffset = homeLayout.getUpWidth();
1126             }
1127         }
1128 
1129         // Position the up container based on where the edge of the home layout should go.
1130         x += positionChild(mUpGoerFive,
1131                 next(x, startOffset, isLayoutRtl), y, contentHeight, isLayoutRtl);
1132         x = next(x, startOffset, isLayoutRtl);
1133 
1134         if (mExpandedActionView == null) {
1135             switch (mNavigationMode) {
1136                 case ActionBar.NAVIGATION_MODE_STANDARD:
1137                     break;
1138                 case ActionBar.NAVIGATION_MODE_LIST:
1139                     if (mListNavLayout != null) {
1140                         if (showTitle) {
1141                             x = next(x, mItemPadding, isLayoutRtl);
1142                         }
1143                         x += positionChild(mListNavLayout, x, y, contentHeight, isLayoutRtl);
1144                         x = next(x, mItemPadding, isLayoutRtl);
1145                     }
1146                     break;
1147                 case ActionBar.NAVIGATION_MODE_TABS:
1148                     if (mTabScrollView != null) {
1149                         if (showTitle) x = next(x, mItemPadding, isLayoutRtl);
1150                         x += positionChild(mTabScrollView, x, y, contentHeight, isLayoutRtl);
1151                         x = next(x, mItemPadding, isLayoutRtl);
1152                     }
1153                     break;
1154             }
1155         }
1156 
1157         if (mMenuView != null && mMenuView.getParent() == this) {
1158             positionChild(mMenuView, menuStart, y, contentHeight, !isLayoutRtl);
1159             menuStart += direction * mMenuView.getMeasuredWidth();
1160         }
1161 
1162         if (mIndeterminateProgressView != null &&
1163                 mIndeterminateProgressView.getVisibility() != GONE) {
1164             positionChild(mIndeterminateProgressView, menuStart, y, contentHeight, !isLayoutRtl);
1165             menuStart += direction * mIndeterminateProgressView.getMeasuredWidth();
1166         }
1167 
1168         View customView = null;
1169         if (mExpandedActionView != null) {
1170             customView = mExpandedActionView;
1171         } else if ((mDisplayOptions & ActionBar.DISPLAY_SHOW_CUSTOM) != 0 &&
1172                 mCustomNavView != null) {
1173             customView = mCustomNavView;
1174         }
1175         if (customView != null) {
1176             final int layoutDirection = getLayoutDirection();
1177             ViewGroup.LayoutParams lp = customView.getLayoutParams();
1178             final ActionBar.LayoutParams ablp = lp instanceof ActionBar.LayoutParams ?
1179                     (ActionBar.LayoutParams) lp : null;
1180             final int gravity = ablp != null ? ablp.gravity : DEFAULT_CUSTOM_GRAVITY;
1181             final int navWidth = customView.getMeasuredWidth();
1182 
1183             int topMargin = 0;
1184             int bottomMargin = 0;
1185             if (ablp != null) {
1186                 x = next(x, ablp.getMarginStart(), isLayoutRtl);
1187                 menuStart += direction * ablp.getMarginEnd();
1188                 topMargin = ablp.topMargin;
1189                 bottomMargin = ablp.bottomMargin;
1190             }
1191 
1192             int hgravity = gravity & Gravity.RELATIVE_HORIZONTAL_GRAVITY_MASK;
1193             // See if we actually have room to truly center; if not push against left or right.
1194             if (hgravity == Gravity.CENTER_HORIZONTAL) {
1195                 final int centeredLeft = ((mRight - mLeft) - navWidth) / 2;
1196                 if (isLayoutRtl) {
1197                     final int centeredStart = centeredLeft + navWidth;
1198                     final int centeredEnd = centeredLeft;
1199                     if (centeredStart > x) {
1200                         hgravity = Gravity.RIGHT;
1201                     } else if (centeredEnd < menuStart) {
1202                         hgravity = Gravity.LEFT;
1203                     }
1204                 } else {
1205                     final int centeredStart = centeredLeft;
1206                     final int centeredEnd = centeredLeft + navWidth;
1207                     if (centeredStart < x) {
1208                         hgravity = Gravity.LEFT;
1209                     } else if (centeredEnd > menuStart) {
1210                         hgravity = Gravity.RIGHT;
1211                     }
1212                 }
1213             } else if (gravity == Gravity.NO_GRAVITY) {
1214                 hgravity = Gravity.START;
1215             }
1216 
1217             int xpos = 0;
1218             switch (Gravity.getAbsoluteGravity(hgravity, layoutDirection)) {
1219                 case Gravity.CENTER_HORIZONTAL:
1220                     xpos = ((mRight - mLeft) - navWidth) / 2;
1221                     break;
1222                 case Gravity.LEFT:
1223                     xpos = isLayoutRtl ? menuStart : x;
1224                     break;
1225                 case Gravity.RIGHT:
1226                     xpos = isLayoutRtl ? x - navWidth : menuStart - navWidth;
1227                     break;
1228             }
1229 
1230             int vgravity = gravity & Gravity.VERTICAL_GRAVITY_MASK;
1231 
1232             if (gravity == Gravity.NO_GRAVITY) {
1233                 vgravity = Gravity.CENTER_VERTICAL;
1234             }
1235 
1236             int ypos = 0;
1237             switch (vgravity) {
1238                 case Gravity.CENTER_VERTICAL:
1239                     final int paddedTop = getPaddingTop();
1240                     final int paddedBottom = mBottom - mTop - getPaddingBottom();
1241                     ypos = ((paddedBottom - paddedTop) - customView.getMeasuredHeight()) / 2;
1242                     break;
1243                 case Gravity.TOP:
1244                     ypos = getPaddingTop() + topMargin;
1245                     break;
1246                 case Gravity.BOTTOM:
1247                     ypos = getHeight() - getPaddingBottom() - customView.getMeasuredHeight()
1248                             - bottomMargin;
1249                     break;
1250             }
1251             final int customWidth = customView.getMeasuredWidth();
1252             customView.layout(xpos, ypos, xpos + customWidth,
1253                     ypos + customView.getMeasuredHeight());
1254             x = next(x, customWidth, isLayoutRtl);
1255         }
1256 
1257         if (mProgressView != null) {
1258             mProgressView.bringToFront();
1259             final int halfProgressHeight = mProgressView.getMeasuredHeight() / 2;
1260             mProgressView.layout(mProgressBarPadding, -halfProgressHeight,
1261                     mProgressBarPadding + mProgressView.getMeasuredWidth(), halfProgressHeight);
1262         }
1263     }
1264 
1265     @Override
generateLayoutParams(AttributeSet attrs)1266     public ViewGroup.LayoutParams generateLayoutParams(AttributeSet attrs) {
1267         return new ActionBar.LayoutParams(getContext(), attrs);
1268     }
1269 
1270     @Override
generateLayoutParams(ViewGroup.LayoutParams lp)1271     public ViewGroup.LayoutParams generateLayoutParams(ViewGroup.LayoutParams lp) {
1272         if (lp == null) {
1273             lp = generateDefaultLayoutParams();
1274         }
1275         return lp;
1276     }
1277 
1278     @Override
onSaveInstanceState()1279     public Parcelable onSaveInstanceState() {
1280         Parcelable superState = super.onSaveInstanceState();
1281         SavedState state = new SavedState(superState);
1282 
1283         if (mExpandedMenuPresenter != null && mExpandedMenuPresenter.mCurrentExpandedItem != null) {
1284             state.expandedMenuItemId = mExpandedMenuPresenter.mCurrentExpandedItem.getItemId();
1285         }
1286 
1287         state.isOverflowOpen = isOverflowMenuShowing();
1288 
1289         return state;
1290     }
1291 
1292     @Override
onRestoreInstanceState(Parcelable p)1293     public void onRestoreInstanceState(Parcelable p) {
1294         SavedState state = (SavedState) p;
1295 
1296         super.onRestoreInstanceState(state.getSuperState());
1297 
1298         if (state.expandedMenuItemId != 0 &&
1299                 mExpandedMenuPresenter != null && mOptionsMenu != null) {
1300             final MenuItem item = mOptionsMenu.findItem(state.expandedMenuItemId);
1301             if (item != null) {
1302                 item.expandActionView();
1303             }
1304         }
1305 
1306         if (state.isOverflowOpen) {
1307             postShowOverflowMenu();
1308         }
1309     }
1310 
setNavigationIcon(Drawable indicator)1311     public void setNavigationIcon(Drawable indicator) {
1312         mHomeLayout.setUpIndicator(indicator);
1313     }
1314 
1315     @Override
setDefaultNavigationIcon(Drawable icon)1316     public void setDefaultNavigationIcon(Drawable icon) {
1317         mHomeLayout.setDefaultUpIndicator(icon);
1318     }
1319 
setNavigationIcon(int resId)1320     public void setNavigationIcon(int resId) {
1321         mHomeLayout.setUpIndicator(resId);
1322     }
1323 
setNavigationContentDescription(CharSequence description)1324     public void setNavigationContentDescription(CharSequence description) {
1325         mHomeDescription = description;
1326         updateHomeAccessibility(mUpGoerFive.isEnabled());
1327     }
1328 
setNavigationContentDescription(int resId)1329     public void setNavigationContentDescription(int resId) {
1330         mHomeDescriptionRes = resId;
1331         mHomeDescription = resId != 0 ? getResources().getText(resId) : null;
1332         updateHomeAccessibility(mUpGoerFive.isEnabled());
1333     }
1334 
1335     @Override
setDefaultNavigationContentDescription(int defaultNavigationContentDescription)1336     public void setDefaultNavigationContentDescription(int defaultNavigationContentDescription) {
1337         if (mDefaultUpDescription == defaultNavigationContentDescription) {
1338             return;
1339         }
1340         mDefaultUpDescription = defaultNavigationContentDescription;
1341         updateHomeAccessibility(mUpGoerFive.isEnabled());
1342     }
1343 
1344     @Override
setMenuCallbacks(MenuPresenter.Callback presenterCallback, MenuBuilder.Callback menuBuilderCallback)1345     public void setMenuCallbacks(MenuPresenter.Callback presenterCallback,
1346             MenuBuilder.Callback menuBuilderCallback) {
1347         if (mActionMenuPresenter != null) {
1348             mActionMenuPresenter.setCallback(presenterCallback);
1349         }
1350         if (mOptionsMenu != null) {
1351             mOptionsMenu.setCallback(menuBuilderCallback);
1352         }
1353     }
1354 
1355     @Override
getMenu()1356     public Menu getMenu() {
1357         return mOptionsMenu;
1358     }
1359 
1360     static class SavedState extends BaseSavedState {
1361         int expandedMenuItemId;
1362         boolean isOverflowOpen;
1363 
SavedState(Parcelable superState)1364         SavedState(Parcelable superState) {
1365             super(superState);
1366         }
1367 
SavedState(Parcel in)1368         private SavedState(Parcel in) {
1369             super(in);
1370             expandedMenuItemId = in.readInt();
1371             isOverflowOpen = in.readInt() != 0;
1372         }
1373 
1374         @Override
writeToParcel(Parcel out, int flags)1375         public void writeToParcel(Parcel out, int flags) {
1376             super.writeToParcel(out, flags);
1377             out.writeInt(expandedMenuItemId);
1378             out.writeInt(isOverflowOpen ? 1 : 0);
1379         }
1380 
1381         public static final Parcelable.Creator<SavedState> CREATOR =
1382                 new Parcelable.Creator<SavedState>() {
1383             public SavedState createFromParcel(Parcel in) {
1384                 return new SavedState(in);
1385             }
1386 
1387             public SavedState[] newArray(int size) {
1388                 return new SavedState[size];
1389             }
1390         };
1391     }
1392 
1393     private static class HomeView extends FrameLayout {
1394         private ImageView mUpView;
1395         private ImageView mIconView;
1396         private int mUpWidth;
1397         private int mStartOffset;
1398         private int mUpIndicatorRes;
1399         private Drawable mDefaultUpIndicator;
1400         private Drawable mUpIndicator;
1401 
1402         private static final long DEFAULT_TRANSITION_DURATION = 150;
1403 
HomeView(Context context)1404         public HomeView(Context context) {
1405             this(context, null);
1406         }
1407 
HomeView(Context context, AttributeSet attrs)1408         public HomeView(Context context, AttributeSet attrs) {
1409             super(context, attrs);
1410             LayoutTransition t = getLayoutTransition();
1411             if (t != null) {
1412                 // Set a lower duration than the default
1413                 t.setDuration(DEFAULT_TRANSITION_DURATION);
1414             }
1415         }
1416 
setShowUp(boolean isUp)1417         public void setShowUp(boolean isUp) {
1418             mUpView.setVisibility(isUp ? VISIBLE : GONE);
1419         }
1420 
setShowIcon(boolean showIcon)1421         public void setShowIcon(boolean showIcon) {
1422             mIconView.setVisibility(showIcon ? VISIBLE : GONE);
1423         }
1424 
setIcon(Drawable icon)1425         public void setIcon(Drawable icon) {
1426             mIconView.setImageDrawable(icon);
1427         }
1428 
setUpIndicator(Drawable d)1429         public void setUpIndicator(Drawable d) {
1430             mUpIndicator = d;
1431             mUpIndicatorRes = 0;
1432             updateUpIndicator();
1433         }
1434 
setDefaultUpIndicator(Drawable d)1435         public void setDefaultUpIndicator(Drawable d) {
1436             mDefaultUpIndicator = d;
1437             updateUpIndicator();
1438         }
1439 
setUpIndicator(int resId)1440         public void setUpIndicator(int resId) {
1441             mUpIndicatorRes = resId;
1442             mUpIndicator = null;
1443             updateUpIndicator();
1444         }
1445 
updateUpIndicator()1446         private void updateUpIndicator() {
1447             if (mUpIndicator != null) {
1448                 mUpView.setImageDrawable(mUpIndicator);
1449             } else if (mUpIndicatorRes != 0) {
1450                 mUpView.setImageDrawable(getContext().getDrawable(mUpIndicatorRes));
1451             } else {
1452                 mUpView.setImageDrawable(mDefaultUpIndicator);
1453             }
1454         }
1455 
1456         @Override
onConfigurationChanged(Configuration newConfig)1457         protected void onConfigurationChanged(Configuration newConfig) {
1458             super.onConfigurationChanged(newConfig);
1459             if (mUpIndicatorRes != 0) {
1460                 // Reload for config change
1461                 updateUpIndicator();
1462             }
1463         }
1464 
1465         @Override
dispatchPopulateAccessibilityEvent(AccessibilityEvent event)1466         public boolean dispatchPopulateAccessibilityEvent(AccessibilityEvent event) {
1467             onPopulateAccessibilityEvent(event);
1468             return true;
1469         }
1470 
1471         @Override
onPopulateAccessibilityEvent(AccessibilityEvent event)1472         public void onPopulateAccessibilityEvent(AccessibilityEvent event) {
1473             super.onPopulateAccessibilityEvent(event);
1474             final CharSequence cdesc = getContentDescription();
1475             if (!TextUtils.isEmpty(cdesc)) {
1476                 event.getText().add(cdesc);
1477             }
1478         }
1479 
1480         @Override
dispatchHoverEvent(MotionEvent event)1481         public boolean dispatchHoverEvent(MotionEvent event) {
1482             // Don't allow children to hover; we want this to be treated as a single component.
1483             return onHoverEvent(event);
1484         }
1485 
1486         @Override
onFinishInflate()1487         protected void onFinishInflate() {
1488             mUpView = (ImageView) findViewById(com.android.internal.R.id.up);
1489             mIconView = (ImageView) findViewById(com.android.internal.R.id.home);
1490             mDefaultUpIndicator = mUpView.getDrawable();
1491         }
1492 
getStartOffset()1493         public int getStartOffset() {
1494             return mUpView.getVisibility() == GONE ? mStartOffset : 0;
1495         }
1496 
getUpWidth()1497         public int getUpWidth() {
1498             return mUpWidth;
1499         }
1500 
1501         @Override
onMeasure(int widthMeasureSpec, int heightMeasureSpec)1502         protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
1503             measureChildWithMargins(mUpView, widthMeasureSpec, 0, heightMeasureSpec, 0);
1504             final LayoutParams upLp = (LayoutParams) mUpView.getLayoutParams();
1505             final int upMargins = upLp.leftMargin + upLp.rightMargin;
1506             mUpWidth = mUpView.getMeasuredWidth();
1507             mStartOffset = mUpWidth + upMargins;
1508             int width = mUpView.getVisibility() == GONE ? 0 : mStartOffset;
1509             int height = upLp.topMargin + mUpView.getMeasuredHeight() + upLp.bottomMargin;
1510 
1511             if (mIconView.getVisibility() != GONE) {
1512                 measureChildWithMargins(mIconView, widthMeasureSpec, width, heightMeasureSpec, 0);
1513                 final LayoutParams iconLp = (LayoutParams) mIconView.getLayoutParams();
1514                 width += iconLp.leftMargin + mIconView.getMeasuredWidth() + iconLp.rightMargin;
1515                 height = Math.max(height,
1516                         iconLp.topMargin + mIconView.getMeasuredHeight() + iconLp.bottomMargin);
1517             } else if (upMargins < 0) {
1518                 // Remove the measurement effects of negative margins used for offsets
1519                 width -= upMargins;
1520             }
1521 
1522             final int widthMode = MeasureSpec.getMode(widthMeasureSpec);
1523             final int heightMode = MeasureSpec.getMode(heightMeasureSpec);
1524             final int widthSize = MeasureSpec.getSize(widthMeasureSpec);
1525             final int heightSize = MeasureSpec.getSize(heightMeasureSpec);
1526 
1527             switch (widthMode) {
1528                 case MeasureSpec.AT_MOST:
1529                     width = Math.min(width, widthSize);
1530                     break;
1531                 case MeasureSpec.EXACTLY:
1532                     width = widthSize;
1533                     break;
1534                 case MeasureSpec.UNSPECIFIED:
1535                 default:
1536                     break;
1537             }
1538             switch (heightMode) {
1539                 case MeasureSpec.AT_MOST:
1540                     height = Math.min(height, heightSize);
1541                     break;
1542                 case MeasureSpec.EXACTLY:
1543                     height = heightSize;
1544                     break;
1545                 case MeasureSpec.UNSPECIFIED:
1546                 default:
1547                     break;
1548             }
1549             setMeasuredDimension(width, height);
1550         }
1551 
1552         @Override
onLayout(boolean changed, int l, int t, int r, int b)1553         protected void onLayout(boolean changed, int l, int t, int r, int b) {
1554             final int vCenter = (b - t) / 2;
1555             final boolean isLayoutRtl = isLayoutRtl();
1556             final int width = getWidth();
1557             int upOffset = 0;
1558             if (mUpView.getVisibility() != GONE) {
1559                 final LayoutParams upLp = (LayoutParams) mUpView.getLayoutParams();
1560                 final int upHeight = mUpView.getMeasuredHeight();
1561                 final int upWidth = mUpView.getMeasuredWidth();
1562                 upOffset = upLp.leftMargin + upWidth + upLp.rightMargin;
1563                 final int upTop = vCenter - upHeight / 2;
1564                 final int upBottom = upTop + upHeight;
1565                 final int upRight;
1566                 final int upLeft;
1567                 if (isLayoutRtl) {
1568                     upRight = width;
1569                     upLeft = upRight - upWidth;
1570                     r -= upOffset;
1571                 } else {
1572                     upRight = upWidth;
1573                     upLeft = 0;
1574                     l += upOffset;
1575                 }
1576                 mUpView.layout(upLeft, upTop, upRight, upBottom);
1577             }
1578 
1579             final LayoutParams iconLp = (LayoutParams) mIconView.getLayoutParams();
1580             final int iconHeight = mIconView.getMeasuredHeight();
1581             final int iconWidth = mIconView.getMeasuredWidth();
1582             final int hCenter = (r - l) / 2;
1583             final int iconTop = Math.max(iconLp.topMargin, vCenter - iconHeight / 2);
1584             final int iconBottom = iconTop + iconHeight;
1585             final int iconLeft;
1586             final int iconRight;
1587             int marginStart = iconLp.getMarginStart();
1588             final int delta = Math.max(marginStart, hCenter - iconWidth / 2);
1589             if (isLayoutRtl) {
1590                 iconRight = width - upOffset - delta;
1591                 iconLeft = iconRight - iconWidth;
1592             } else {
1593                 iconLeft = upOffset + delta;
1594                 iconRight = iconLeft + iconWidth;
1595             }
1596             mIconView.layout(iconLeft, iconTop, iconRight, iconBottom);
1597         }
1598     }
1599 
1600     private class ExpandedActionViewMenuPresenter implements MenuPresenter {
1601         MenuBuilder mMenu;
1602         MenuItemImpl mCurrentExpandedItem;
1603 
1604         @Override
initForMenu(Context context, MenuBuilder menu)1605         public void initForMenu(Context context, MenuBuilder menu) {
1606             // Clear the expanded action view when menus change.
1607             if (mMenu != null && mCurrentExpandedItem != null) {
1608                 mMenu.collapseItemActionView(mCurrentExpandedItem);
1609             }
1610             mMenu = menu;
1611         }
1612 
1613         @Override
getMenuView(ViewGroup root)1614         public MenuView getMenuView(ViewGroup root) {
1615             return null;
1616         }
1617 
1618         @Override
updateMenuView(boolean cleared)1619         public void updateMenuView(boolean cleared) {
1620             // Make sure the expanded item we have is still there.
1621             if (mCurrentExpandedItem != null) {
1622                 boolean found = false;
1623 
1624                 if (mMenu != null) {
1625                     final int count = mMenu.size();
1626                     for (int i = 0; i < count; i++) {
1627                         final MenuItem item = mMenu.getItem(i);
1628                         if (item == mCurrentExpandedItem) {
1629                             found = true;
1630                             break;
1631                         }
1632                     }
1633                 }
1634 
1635                 if (!found) {
1636                     // The item we had expanded disappeared. Collapse.
1637                     collapseItemActionView(mMenu, mCurrentExpandedItem);
1638                 }
1639             }
1640         }
1641 
1642         @Override
setCallback(Callback cb)1643         public void setCallback(Callback cb) {
1644         }
1645 
1646         @Override
onSubMenuSelected(SubMenuBuilder subMenu)1647         public boolean onSubMenuSelected(SubMenuBuilder subMenu) {
1648             return false;
1649         }
1650 
1651         @Override
onCloseMenu(MenuBuilder menu, boolean allMenusAreClosing)1652         public void onCloseMenu(MenuBuilder menu, boolean allMenusAreClosing) {
1653         }
1654 
1655         @Override
flagActionItems()1656         public boolean flagActionItems() {
1657             return false;
1658         }
1659 
1660         @Override
expandItemActionView(MenuBuilder menu, MenuItemImpl item)1661         public boolean expandItemActionView(MenuBuilder menu, MenuItemImpl item) {
1662             ActionBarTransition.beginDelayedTransition(ActionBarView.this);
1663 
1664             mExpandedActionView = item.getActionView();
1665             mExpandedHomeLayout.setIcon(mIcon.getConstantState().newDrawable(getResources()));
1666             mCurrentExpandedItem = item;
1667             if (mExpandedActionView.getParent() != ActionBarView.this) {
1668                 addView(mExpandedActionView);
1669             }
1670             if (mExpandedHomeLayout.getParent() != mUpGoerFive) {
1671                 mUpGoerFive.addView(mExpandedHomeLayout);
1672             }
1673             mHomeLayout.setVisibility(GONE);
1674             if (mTitleLayout != null) mTitleLayout.setVisibility(GONE);
1675             if (mTabScrollView != null) mTabScrollView.setVisibility(GONE);
1676             if (mSpinner != null) mSpinner.setVisibility(GONE);
1677             if (mCustomNavView != null) mCustomNavView.setVisibility(GONE);
1678             setHomeButtonEnabled(false, false);
1679             requestLayout();
1680             item.setActionViewExpanded(true);
1681 
1682             if (mExpandedActionView instanceof CollapsibleActionView) {
1683                 ((CollapsibleActionView) mExpandedActionView).onActionViewExpanded();
1684             }
1685 
1686             return true;
1687         }
1688 
1689         @Override
collapseItemActionView(MenuBuilder menu, MenuItemImpl item)1690         public boolean collapseItemActionView(MenuBuilder menu, MenuItemImpl item) {
1691             ActionBarTransition.beginDelayedTransition(ActionBarView.this);
1692 
1693             // Do this before detaching the actionview from the hierarchy, in case
1694             // it needs to dismiss the soft keyboard, etc.
1695             if (mExpandedActionView instanceof CollapsibleActionView) {
1696                 ((CollapsibleActionView) mExpandedActionView).onActionViewCollapsed();
1697             }
1698 
1699             removeView(mExpandedActionView);
1700             mUpGoerFive.removeView(mExpandedHomeLayout);
1701             mExpandedActionView = null;
1702             if ((mDisplayOptions & ActionBar.DISPLAY_SHOW_HOME) != 0) {
1703                 mHomeLayout.setVisibility(VISIBLE);
1704             }
1705             if ((mDisplayOptions & ActionBar.DISPLAY_SHOW_TITLE) != 0) {
1706                 if (mTitleLayout == null) {
1707                     initTitle();
1708                 } else {
1709                     mTitleLayout.setVisibility(VISIBLE);
1710                 }
1711             }
1712             if (mTabScrollView != null) mTabScrollView.setVisibility(VISIBLE);
1713             if (mSpinner != null) mSpinner.setVisibility(VISIBLE);
1714             if (mCustomNavView != null) mCustomNavView.setVisibility(VISIBLE);
1715 
1716             mExpandedHomeLayout.setIcon(null);
1717             mCurrentExpandedItem = null;
1718             setHomeButtonEnabled(mWasHomeEnabled); // Set by expandItemActionView above
1719             requestLayout();
1720             item.setActionViewExpanded(false);
1721 
1722             return true;
1723         }
1724 
1725         @Override
getId()1726         public int getId() {
1727             return 0;
1728         }
1729 
1730         @Override
onSaveInstanceState()1731         public Parcelable onSaveInstanceState() {
1732             return null;
1733         }
1734 
1735         @Override
onRestoreInstanceState(Parcelable state)1736         public void onRestoreInstanceState(Parcelable state) {
1737         }
1738     }
1739 }
1740