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