2 * Copyright (C) 2010 The Android Open Source Project
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
17 package com.actionbarsherlock.internal.widget;
19 import org.xmlpull.v1.XmlPullParser;
20 import android.app.Activity;
21 import android.content.Context;
22 import android.content.pm.ApplicationInfo;
23 import android.content.pm.PackageManager;
24 import android.content.pm.PackageManager.NameNotFoundException;
25 import android.content.res.AssetManager;
26 import android.content.res.Configuration;
27 import android.content.res.TypedArray;
28 import android.content.res.XmlResourceParser;
29 import android.graphics.drawable.Drawable;
30 import android.os.Build;
31 import android.os.Parcel;
32 import android.os.Parcelable;
33 import android.text.TextUtils;
34 import android.util.AttributeSet;
35 import android.util.Log;
36 import android.view.Gravity;
37 import android.view.LayoutInflater;
38 import android.view.MotionEvent;
39 import android.view.View;
40 import android.view.ViewGroup;
41 import android.view.ViewParent;
42 import android.view.accessibility.AccessibilityEvent;
43 import android.widget.FrameLayout;
44 import android.widget.ImageView;
45 import android.widget.LinearLayout;
46 import android.widget.SpinnerAdapter;
47 import android.widget.TextView;
49 import com.actionbarsherlock.R;
50 import com.actionbarsherlock.app.ActionBar;
51 import com.actionbarsherlock.app.ActionBar.OnNavigationListener;
52 import com.actionbarsherlock.internal.ActionBarSherlockCompat;
53 import com.actionbarsherlock.internal.view.menu.ActionMenuItem;
54 import com.actionbarsherlock.internal.view.menu.ActionMenuPresenter;
55 import com.actionbarsherlock.internal.view.menu.ActionMenuView;
56 import com.actionbarsherlock.internal.view.menu.MenuBuilder;
57 import com.actionbarsherlock.internal.view.menu.MenuItemImpl;
58 import com.actionbarsherlock.internal.view.menu.MenuPresenter;
59 import com.actionbarsherlock.internal.view.menu.MenuView;
60 import com.actionbarsherlock.internal.view.menu.SubMenuBuilder;
61 import com.actionbarsherlock.view.CollapsibleActionView;
62 import com.actionbarsherlock.view.Menu;
63 import com.actionbarsherlock.view.MenuItem;
64 import com.actionbarsherlock.view.Window;
66 import static com.actionbarsherlock.internal.ResourcesCompat.getResources_getBoolean;
71 public class ActionBarView extends AbsActionBarView {
72 private static final String TAG = "ActionBarView";
73 private static final boolean DEBUG = false;
76 * Display options applied by default
78 public static final int DISPLAY_DEFAULT = 0;
81 * Display options that require re-layout as opposed to a simple invalidate
83 private static final int DISPLAY_RELAYOUT_MASK =
84 ActionBar.DISPLAY_SHOW_HOME |
85 ActionBar.DISPLAY_USE_LOGO |
86 ActionBar.DISPLAY_HOME_AS_UP |
87 ActionBar.DISPLAY_SHOW_CUSTOM |
88 ActionBar.DISPLAY_SHOW_TITLE;
90 private static final int DEFAULT_CUSTOM_GRAVITY = Gravity.LEFT | Gravity.CENTER_VERTICAL;
92 private int mNavigationMode;
93 private int mDisplayOptions = -1;
94 private CharSequence mTitle;
95 private CharSequence mSubtitle;
96 private Drawable mIcon;
97 private Drawable mLogo;
99 private HomeView mHomeLayout;
100 private HomeView mExpandedHomeLayout;
101 private LinearLayout mTitleLayout;
102 private TextView mTitleView;
103 private TextView mSubtitleView;
104 private View mTitleUpView;
106 private IcsSpinner mSpinner;
107 private IcsLinearLayout mListNavLayout;
108 private ScrollingTabContainerView mTabScrollView;
109 private View mCustomNavView;
110 private IcsProgressBar mProgressView;
111 private IcsProgressBar mIndeterminateProgressView;
113 private int mProgressBarPadding;
114 private int mItemPadding;
116 private int mTitleStyleRes;
117 private int mSubtitleStyleRes;
118 private int mProgressStyle;
119 private int mIndeterminateProgressStyle;
121 private boolean mUserTitle;
122 private boolean mIncludeTabs;
123 private boolean mIsCollapsable;
124 private boolean mIsCollapsed;
126 private MenuBuilder mOptionsMenu;
128 private ActionBarContextView mContextView;
130 private ActionMenuItem mLogoNavItem;
132 private SpinnerAdapter mSpinnerAdapter;
133 private OnNavigationListener mCallback;
135 //UNUSED private Runnable mTabSelector;
137 private ExpandedActionViewMenuPresenter mExpandedMenuPresenter;
138 View mExpandedActionView;
140 Window.Callback mWindowCallback;
142 @SuppressWarnings("rawtypes")
143 private final IcsAdapterView.OnItemSelectedListener mNavItemSelectedListener =
144 new IcsAdapterView.OnItemSelectedListener() {
145 public void onItemSelected(IcsAdapterView parent, View view, int position, long id) {
146 if (mCallback != null) {
147 mCallback.onNavigationItemSelected(position, id);
150 public void onNothingSelected(IcsAdapterView parent) {
155 private final OnClickListener mExpandedActionViewUpListener = new OnClickListener() {
157 public void onClick(View v) {
158 final MenuItemImpl item = mExpandedMenuPresenter.mCurrentExpandedItem;
160 item.collapseActionView();
165 private final OnClickListener mUpClickListener = new OnClickListener() {
166 public void onClick(View v) {
167 mWindowCallback.onMenuItemSelected(Window.FEATURE_OPTIONS_PANEL, mLogoNavItem);
171 public ActionBarView(Context context, AttributeSet attrs) {
172 super(context, attrs);
174 // Background is always provided by the container.
175 setBackgroundResource(0);
177 TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.SherlockActionBar,
178 R.attr.actionBarStyle, 0);
180 ApplicationInfo appInfo = context.getApplicationInfo();
181 PackageManager pm = context.getPackageManager();
182 mNavigationMode = a.getInt(R.styleable.SherlockActionBar_navigationMode,
183 ActionBar.NAVIGATION_MODE_STANDARD);
184 mTitle = a.getText(R.styleable.SherlockActionBar_title);
185 mSubtitle = a.getText(R.styleable.SherlockActionBar_subtitle);
187 mLogo = a.getDrawable(R.styleable.SherlockActionBar_logo);
189 if (Build.VERSION.SDK_INT < Build.VERSION_CODES.HONEYCOMB) {
190 if (context instanceof Activity) {
191 //Even though native methods existed in API 9 and 10 they don't work
192 //so just parse the manifest to look for the logo pre-Honeycomb
193 final int resId = loadLogoFromManifest((Activity) context);
195 mLogo = context.getResources().getDrawable(resId);
199 if (context instanceof Activity) {
201 mLogo = pm.getActivityLogo(((Activity) context).getComponentName());
202 } catch (NameNotFoundException e) {
203 Log.e(TAG, "Activity component name not found!", e);
207 mLogo = appInfo.loadLogo(pm);
212 mIcon = a.getDrawable(R.styleable.SherlockActionBar_icon);
214 if (context instanceof Activity) {
216 mIcon = pm.getActivityIcon(((Activity) context).getComponentName());
217 } catch (NameNotFoundException e) {
218 Log.e(TAG, "Activity component name not found!", e);
222 mIcon = appInfo.loadIcon(pm);
226 final LayoutInflater inflater = LayoutInflater.from(context);
228 final int homeResId = a.getResourceId(
229 R.styleable.SherlockActionBar_homeLayout,
230 R.layout.abs__action_bar_home);
232 mHomeLayout = (HomeView) inflater.inflate(homeResId, this, false);
234 mExpandedHomeLayout = (HomeView) inflater.inflate(homeResId, this, false);
235 mExpandedHomeLayout.setUp(true);
236 mExpandedHomeLayout.setOnClickListener(mExpandedActionViewUpListener);
237 mExpandedHomeLayout.setContentDescription(getResources().getText(
238 R.string.abs__action_bar_up_description));
240 mTitleStyleRes = a.getResourceId(R.styleable.SherlockActionBar_titleTextStyle, 0);
241 mSubtitleStyleRes = a.getResourceId(R.styleable.SherlockActionBar_subtitleTextStyle, 0);
242 mProgressStyle = a.getResourceId(R.styleable.SherlockActionBar_progressBarStyle, 0);
243 mIndeterminateProgressStyle = a.getResourceId(
244 R.styleable.SherlockActionBar_indeterminateProgressStyle, 0);
246 mProgressBarPadding = a.getDimensionPixelOffset(R.styleable.SherlockActionBar_progressBarPadding, 0);
247 mItemPadding = a.getDimensionPixelOffset(R.styleable.SherlockActionBar_itemPadding, 0);
249 setDisplayOptions(a.getInt(R.styleable.SherlockActionBar_displayOptions, DISPLAY_DEFAULT));
251 final int customNavId = a.getResourceId(R.styleable.SherlockActionBar_customNavigationLayout, 0);
252 if (customNavId != 0) {
253 mCustomNavView = inflater.inflate(customNavId, this, false);
254 mNavigationMode = ActionBar.NAVIGATION_MODE_STANDARD;
255 setDisplayOptions(mDisplayOptions | ActionBar.DISPLAY_SHOW_CUSTOM);
258 mContentHeight = a.getLayoutDimension(R.styleable.SherlockActionBar_height, 0);
262 mLogoNavItem = new ActionMenuItem(context, 0, android.R.id.home, 0, 0, mTitle);
263 mHomeLayout.setOnClickListener(mUpClickListener);
264 mHomeLayout.setClickable(true);
265 mHomeLayout.setFocusable(true);
269 * Attempt to programmatically load the logo from the manifest file of an
270 * activity by using an XML pull parser. This should allow us to read the
271 * logo attribute regardless of the platform it is being run on.
273 * @param activity Activity instance.
274 * @return Logo resource ID.
276 private static int loadLogoFromManifest(Activity activity) {
279 final String thisPackage = activity.getClass().getName();
280 if (DEBUG) Log.i(TAG, "Parsing AndroidManifest.xml for " + thisPackage);
282 final String packageName = activity.getApplicationInfo().packageName;
283 final AssetManager am = activity.createPackageContext(packageName, 0).getAssets();
284 final XmlResourceParser xml = am.openXmlResourceParser("AndroidManifest.xml");
286 int eventType = xml.getEventType();
287 while (eventType != XmlPullParser.END_DOCUMENT) {
288 if (eventType == XmlPullParser.START_TAG) {
289 String name = xml.getName();
291 if ("application".equals(name)) {
292 //Check if the <application> has the attribute
293 if (DEBUG) Log.d(TAG, "Got <application>");
295 for (int i = xml.getAttributeCount() - 1; i >= 0; i--) {
296 if (DEBUG) Log.d(TAG, xml.getAttributeName(i) + ": " + xml.getAttributeValue(i));
298 if ("logo".equals(xml.getAttributeName(i))) {
299 logo = xml.getAttributeResourceValue(i, 0);
300 break; //out of for loop
303 } else if ("activity".equals(name)) {
304 //Check if the <activity> is us and has the attribute
305 if (DEBUG) Log.d(TAG, "Got <activity>");
306 Integer activityLogo = null;
307 String activityPackage = null;
308 boolean isOurActivity = false;
310 for (int i = xml.getAttributeCount() - 1; i >= 0; i--) {
311 if (DEBUG) Log.d(TAG, xml.getAttributeName(i) + ": " + xml.getAttributeValue(i));
313 //We need both uiOptions and name attributes
314 String attrName = xml.getAttributeName(i);
315 if ("logo".equals(attrName)) {
316 activityLogo = xml.getAttributeResourceValue(i, 0);
317 } else if ("name".equals(attrName)) {
318 activityPackage = ActionBarSherlockCompat.cleanActivityName(packageName, xml.getAttributeValue(i));
319 if (!thisPackage.equals(activityPackage)) {
320 break; //on to the next
322 isOurActivity = true;
325 //Make sure we have both attributes before processing
326 if ((activityLogo != null) && (activityPackage != null)) {
327 //Our activity, logo specified, override with our value
328 logo = activityLogo.intValue();
332 //If we matched our activity but it had no logo don't
333 //do any more processing of the manifest
338 eventType = xml.nextToken();
340 } catch (Exception e) {
343 if (DEBUG) Log.i(TAG, "Returning " + Integer.toHexString(logo));
348 * Must be public so we can dispatch pre-2.2 via ActionBarImpl.
351 public void onConfigurationChanged(Configuration newConfig) {
352 super.onConfigurationChanged(newConfig);
355 mSubtitleView = null;
357 if (mTitleLayout != null && mTitleLayout.getParent() == this) {
358 removeView(mTitleLayout);
361 if ((mDisplayOptions & ActionBar.DISPLAY_SHOW_TITLE) != 0) {
365 if (mTabScrollView != null && mIncludeTabs) {
366 ViewGroup.LayoutParams lp = mTabScrollView.getLayoutParams();
368 lp.width = LayoutParams.WRAP_CONTENT;
369 lp.height = LayoutParams.MATCH_PARENT;
371 mTabScrollView.setAllowCollapse(true);
376 * Set the window callback used to invoke menu items; used for dispatching home button presses.
377 * @param cb Window callback to dispatch to
379 public void setWindowCallback(Window.Callback cb) {
380 mWindowCallback = cb;
384 public void onDetachedFromWindow() {
385 super.onDetachedFromWindow();
386 //UNUSED removeCallbacks(mTabSelector);
387 if (mActionMenuPresenter != null) {
388 mActionMenuPresenter.hideOverflowMenu();
389 mActionMenuPresenter.hideSubMenus();
394 public boolean shouldDelayChildPressedState() {
398 public void initProgress() {
399 mProgressView = new IcsProgressBar(mContext, null, 0, mProgressStyle);
400 mProgressView.setId(R.id.abs__progress_horizontal);
401 mProgressView.setMax(10000);
402 addView(mProgressView);
405 public void initIndeterminateProgress() {
406 mIndeterminateProgressView = new IcsProgressBar(mContext, null, 0, mIndeterminateProgressStyle);
407 mIndeterminateProgressView.setId(R.id.abs__progress_circular);
408 addView(mIndeterminateProgressView);
412 public void setSplitActionBar(boolean splitActionBar) {
413 if (mSplitActionBar != splitActionBar) {
414 if (mMenuView != null) {
415 final ViewGroup oldParent = (ViewGroup) mMenuView.getParent();
416 if (oldParent != null) {
417 oldParent.removeView(mMenuView);
419 if (splitActionBar) {
420 if (mSplitView != null) {
421 mSplitView.addView(mMenuView);
427 if (mSplitView != null) {
428 mSplitView.setVisibility(splitActionBar ? VISIBLE : GONE);
430 super.setSplitActionBar(splitActionBar);
434 public boolean isSplitActionBar() {
435 return mSplitActionBar;
438 public boolean hasEmbeddedTabs() {
442 public void setEmbeddedTabView(ScrollingTabContainerView tabs) {
443 if (mTabScrollView != null) {
444 removeView(mTabScrollView);
446 mTabScrollView = tabs;
447 mIncludeTabs = tabs != null;
448 if (mIncludeTabs && mNavigationMode == ActionBar.NAVIGATION_MODE_TABS) {
449 addView(mTabScrollView);
450 ViewGroup.LayoutParams lp = mTabScrollView.getLayoutParams();
451 lp.width = LayoutParams.WRAP_CONTENT;
452 lp.height = LayoutParams.MATCH_PARENT;
453 tabs.setAllowCollapse(true);
457 public void setCallback(OnNavigationListener callback) {
458 mCallback = callback;
461 public void setMenu(Menu menu, MenuPresenter.Callback cb) {
462 if (menu == mOptionsMenu) return;
464 if (mOptionsMenu != null) {
465 mOptionsMenu.removeMenuPresenter(mActionMenuPresenter);
466 mOptionsMenu.removeMenuPresenter(mExpandedMenuPresenter);
469 MenuBuilder builder = (MenuBuilder) menu;
470 mOptionsMenu = builder;
471 if (mMenuView != null) {
472 final ViewGroup oldParent = (ViewGroup) mMenuView.getParent();
473 if (oldParent != null) {
474 oldParent.removeView(mMenuView);
477 if (mActionMenuPresenter == null) {
478 mActionMenuPresenter = new ActionMenuPresenter(mContext);
479 mActionMenuPresenter.setCallback(cb);
480 mActionMenuPresenter.setId(R.id.abs__action_menu_presenter);
481 mExpandedMenuPresenter = new ExpandedActionViewMenuPresenter();
484 ActionMenuView menuView;
485 final LayoutParams layoutParams = new LayoutParams(LayoutParams.WRAP_CONTENT,
486 LayoutParams.MATCH_PARENT);
487 if (!mSplitActionBar) {
488 mActionMenuPresenter.setExpandedActionViewsExclusive(
489 getResources_getBoolean(getContext(),
490 R.bool.abs__action_bar_expanded_action_views_exclusive));
491 configPresenters(builder);
492 menuView = (ActionMenuView) mActionMenuPresenter.getMenuView(this);
493 final ViewGroup oldParent = (ViewGroup) menuView.getParent();
494 if (oldParent != null && oldParent != this) {
495 oldParent.removeView(menuView);
497 addView(menuView, layoutParams);
499 mActionMenuPresenter.setExpandedActionViewsExclusive(false);
500 // Allow full screen width in split mode.
501 mActionMenuPresenter.setWidthLimit(
502 getContext().getResources().getDisplayMetrics().widthPixels, true);
503 // No limit to the item count; use whatever will fit.
504 mActionMenuPresenter.setItemLimit(Integer.MAX_VALUE);
505 // Span the whole width
506 layoutParams.width = LayoutParams.MATCH_PARENT;
507 configPresenters(builder);
508 menuView = (ActionMenuView) mActionMenuPresenter.getMenuView(this);
509 if (mSplitView != null) {
510 final ViewGroup oldParent = (ViewGroup) menuView.getParent();
511 if (oldParent != null && oldParent != mSplitView) {
512 oldParent.removeView(menuView);
514 menuView.setVisibility(getAnimatedVisibility());
515 mSplitView.addView(menuView, layoutParams);
517 // We'll add this later if we missed it this time.
518 menuView.setLayoutParams(layoutParams);
521 mMenuView = menuView;
524 private void configPresenters(MenuBuilder builder) {
525 if (builder != null) {
526 builder.addMenuPresenter(mActionMenuPresenter);
527 builder.addMenuPresenter(mExpandedMenuPresenter);
529 mActionMenuPresenter.initForMenu(mContext, null);
530 mExpandedMenuPresenter.initForMenu(mContext, null);
531 mActionMenuPresenter.updateMenuView(true);
532 mExpandedMenuPresenter.updateMenuView(true);
536 public boolean hasExpandedActionView() {
537 return mExpandedMenuPresenter != null &&
538 mExpandedMenuPresenter.mCurrentExpandedItem != null;
541 public void collapseActionView() {
542 final MenuItemImpl item = mExpandedMenuPresenter == null ? null :
543 mExpandedMenuPresenter.mCurrentExpandedItem;
545 item.collapseActionView();
549 public void setCustomNavigationView(View view) {
550 final boolean showCustom = (mDisplayOptions & ActionBar.DISPLAY_SHOW_CUSTOM) != 0;
551 if (mCustomNavView != null && showCustom) {
552 removeView(mCustomNavView);
554 mCustomNavView = view;
555 if (mCustomNavView != null && showCustom) {
556 addView(mCustomNavView);
560 public CharSequence getTitle() {
565 * Set the action bar title. This will always replace or override window titles.
566 * @param title Title to set
568 * @see #setWindowTitle(CharSequence)
570 public void setTitle(CharSequence title) {
576 * Set the window title. A window title will always be replaced or overridden by a user title.
577 * @param title Title to set
579 * @see #setTitle(CharSequence)
581 public void setWindowTitle(CharSequence title) {
587 private void setTitleImpl(CharSequence title) {
589 if (mTitleView != null) {
590 mTitleView.setText(title);
591 final boolean visible = mExpandedActionView == null &&
592 (mDisplayOptions & ActionBar.DISPLAY_SHOW_TITLE) != 0 &&
593 (!TextUtils.isEmpty(mTitle) || !TextUtils.isEmpty(mSubtitle));
594 mTitleLayout.setVisibility(visible ? VISIBLE : GONE);
596 if (mLogoNavItem != null) {
597 mLogoNavItem.setTitle(title);
601 public CharSequence getSubtitle() {
605 public void setSubtitle(CharSequence subtitle) {
606 mSubtitle = subtitle;
607 if (mSubtitleView != null) {
608 mSubtitleView.setText(subtitle);
609 mSubtitleView.setVisibility(subtitle != null ? VISIBLE : GONE);
610 final boolean visible = mExpandedActionView == null &&
611 (mDisplayOptions & ActionBar.DISPLAY_SHOW_TITLE) != 0 &&
612 (!TextUtils.isEmpty(mTitle) || !TextUtils.isEmpty(mSubtitle));
613 mTitleLayout.setVisibility(visible ? VISIBLE : GONE);
617 public void setHomeButtonEnabled(boolean enable) {
618 mHomeLayout.setEnabled(enable);
619 mHomeLayout.setFocusable(enable);
620 // Make sure the home button has an accurate content description for accessibility.
622 mHomeLayout.setContentDescription(null);
623 } else if ((mDisplayOptions & ActionBar.DISPLAY_HOME_AS_UP) != 0) {
624 mHomeLayout.setContentDescription(mContext.getResources().getText(
625 R.string.abs__action_bar_up_description));
627 mHomeLayout.setContentDescription(mContext.getResources().getText(
628 R.string.abs__action_bar_home_description));
632 public void setDisplayOptions(int options) {
633 final int flagsChanged = mDisplayOptions == -1 ? -1 : options ^ mDisplayOptions;
634 mDisplayOptions = options;
636 if ((flagsChanged & DISPLAY_RELAYOUT_MASK) != 0) {
637 final boolean showHome = (options & ActionBar.DISPLAY_SHOW_HOME) != 0;
638 final int vis = showHome && mExpandedActionView == null ? VISIBLE : GONE;
639 mHomeLayout.setVisibility(vis);
641 if ((flagsChanged & ActionBar.DISPLAY_HOME_AS_UP) != 0) {
642 final boolean setUp = (options & ActionBar.DISPLAY_HOME_AS_UP) != 0;
643 mHomeLayout.setUp(setUp);
645 // Showing home as up implicitly enables interaction with it.
646 // In honeycomb it was always enabled, so make this transition
647 // a bit easier for developers in the common case.
648 // (It would be silly to show it as up without responding to it.)
650 setHomeButtonEnabled(true);
654 if ((flagsChanged & ActionBar.DISPLAY_USE_LOGO) != 0) {
655 final boolean logoVis = mLogo != null && (options & ActionBar.DISPLAY_USE_LOGO) != 0;
656 mHomeLayout.setIcon(logoVis ? mLogo : mIcon);
659 if ((flagsChanged & ActionBar.DISPLAY_SHOW_TITLE) != 0) {
660 if ((options & ActionBar.DISPLAY_SHOW_TITLE) != 0) {
663 removeView(mTitleLayout);
667 if (mTitleLayout != null && (flagsChanged &
668 (ActionBar.DISPLAY_HOME_AS_UP | ActionBar.DISPLAY_SHOW_HOME)) != 0) {
669 final boolean homeAsUp = (mDisplayOptions & ActionBar.DISPLAY_HOME_AS_UP) != 0;
670 mTitleUpView.setVisibility(!showHome ? (homeAsUp ? VISIBLE : INVISIBLE) : GONE);
671 mTitleLayout.setEnabled(!showHome && homeAsUp);
674 if ((flagsChanged & ActionBar.DISPLAY_SHOW_CUSTOM) != 0 && mCustomNavView != null) {
675 if ((options & ActionBar.DISPLAY_SHOW_CUSTOM) != 0) {
676 addView(mCustomNavView);
678 removeView(mCustomNavView);
687 // Make sure the home button has an accurate content description for accessibility.
688 if (!mHomeLayout.isEnabled()) {
689 mHomeLayout.setContentDescription(null);
690 } else if ((options & ActionBar.DISPLAY_HOME_AS_UP) != 0) {
691 mHomeLayout.setContentDescription(mContext.getResources().getText(
692 R.string.abs__action_bar_up_description));
694 mHomeLayout.setContentDescription(mContext.getResources().getText(
695 R.string.abs__action_bar_home_description));
699 public void setIcon(Drawable icon) {
702 ((mDisplayOptions & ActionBar.DISPLAY_USE_LOGO) == 0 || mLogo == null)) {
703 mHomeLayout.setIcon(icon);
707 public void setIcon(int resId) {
708 setIcon(mContext.getResources().getDrawable(resId));
711 public void setLogo(Drawable logo) {
713 if (logo != null && (mDisplayOptions & ActionBar.DISPLAY_USE_LOGO) != 0) {
714 mHomeLayout.setIcon(logo);
718 public void setLogo(int resId) {
719 setLogo(mContext.getResources().getDrawable(resId));
722 public void setNavigationMode(int mode) {
723 final int oldMode = mNavigationMode;
724 if (mode != oldMode) {
726 case ActionBar.NAVIGATION_MODE_LIST:
727 if (mListNavLayout != null) {
728 removeView(mListNavLayout);
731 case ActionBar.NAVIGATION_MODE_TABS:
732 if (mTabScrollView != null && mIncludeTabs) {
733 removeView(mTabScrollView);
738 case ActionBar.NAVIGATION_MODE_LIST:
739 if (mSpinner == null) {
740 mSpinner = new IcsSpinner(mContext, null,
741 R.attr.actionDropDownStyle);
742 mListNavLayout = (IcsLinearLayout) LayoutInflater.from(mContext)
743 .inflate(R.layout.abs__action_bar_tab_bar_view, null);
744 LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(
745 LayoutParams.WRAP_CONTENT, LayoutParams.MATCH_PARENT);
746 params.gravity = Gravity.CENTER;
747 mListNavLayout.addView(mSpinner, params);
749 if (mSpinner.getAdapter() != mSpinnerAdapter) {
750 mSpinner.setAdapter(mSpinnerAdapter);
752 mSpinner.setOnItemSelectedListener(mNavItemSelectedListener);
753 addView(mListNavLayout);
755 case ActionBar.NAVIGATION_MODE_TABS:
756 if (mTabScrollView != null && mIncludeTabs) {
757 addView(mTabScrollView);
761 mNavigationMode = mode;
766 public void setDropdownAdapter(SpinnerAdapter adapter) {
767 mSpinnerAdapter = adapter;
768 if (mSpinner != null) {
769 mSpinner.setAdapter(adapter);
773 public SpinnerAdapter getDropdownAdapter() {
774 return mSpinnerAdapter;
777 public void setDropdownSelectedPosition(int position) {
778 mSpinner.setSelection(position);
781 public int getDropdownSelectedPosition() {
782 return mSpinner.getSelectedItemPosition();
785 public View getCustomNavigationView() {
786 return mCustomNavView;
789 public int getNavigationMode() {
790 return mNavigationMode;
793 public int getDisplayOptions() {
794 return mDisplayOptions;
798 protected ViewGroup.LayoutParams generateDefaultLayoutParams() {
799 // Used by custom nav views if they don't supply layout params. Everything else
800 // added to an ActionBarView should have them already.
801 return new ActionBar.LayoutParams(DEFAULT_CUSTOM_GRAVITY);
805 protected void onFinishInflate() {
806 super.onFinishInflate();
808 addView(mHomeLayout);
810 if (mCustomNavView != null && (mDisplayOptions & ActionBar.DISPLAY_SHOW_CUSTOM) != 0) {
811 final ViewParent parent = mCustomNavView.getParent();
812 if (parent != this) {
813 if (parent instanceof ViewGroup) {
814 ((ViewGroup) parent).removeView(mCustomNavView);
816 addView(mCustomNavView);
821 private void initTitle() {
822 if (mTitleLayout == null) {
823 LayoutInflater inflater = LayoutInflater.from(getContext());
824 mTitleLayout = (LinearLayout) inflater.inflate(R.layout.abs__action_bar_title_item,
826 mTitleView = (TextView) mTitleLayout.findViewById(R.id.abs__action_bar_title);
827 mSubtitleView = (TextView) mTitleLayout.findViewById(R.id.abs__action_bar_subtitle);
828 mTitleUpView = mTitleLayout.findViewById(R.id.abs__up);
830 mTitleLayout.setOnClickListener(mUpClickListener);
832 if (mTitleStyleRes != 0) {
833 mTitleView.setTextAppearance(mContext, mTitleStyleRes);
835 if (mTitle != null) {
836 mTitleView.setText(mTitle);
839 if (mSubtitleStyleRes != 0) {
840 mSubtitleView.setTextAppearance(mContext, mSubtitleStyleRes);
842 if (mSubtitle != null) {
843 mSubtitleView.setText(mSubtitle);
844 mSubtitleView.setVisibility(VISIBLE);
847 final boolean homeAsUp = (mDisplayOptions & ActionBar.DISPLAY_HOME_AS_UP) != 0;
848 final boolean showHome = (mDisplayOptions & ActionBar.DISPLAY_SHOW_HOME) != 0;
849 mTitleUpView.setVisibility(!showHome ? (homeAsUp ? VISIBLE : INVISIBLE) : GONE);
850 mTitleLayout.setEnabled(homeAsUp && !showHome);
853 addView(mTitleLayout);
854 if (mExpandedActionView != null ||
855 (TextUtils.isEmpty(mTitle) && TextUtils.isEmpty(mSubtitle))) {
856 // Don't show while in expanded mode or with empty text
857 mTitleLayout.setVisibility(GONE);
861 public void setContextView(ActionBarContextView view) {
865 public void setCollapsable(boolean collapsable) {
866 mIsCollapsable = collapsable;
869 public boolean isCollapsed() {
874 protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
875 final int childCount = getChildCount();
876 if (mIsCollapsable) {
877 int visibleChildren = 0;
878 for (int i = 0; i < childCount; i++) {
879 final View child = getChildAt(i);
880 if (child.getVisibility() != GONE &&
881 !(child == mMenuView && mMenuView.getChildCount() == 0)) {
886 if (visibleChildren == 0) {
887 // No size for an empty action bar when collapsable.
888 setMeasuredDimension(0, 0);
893 mIsCollapsed = false;
895 int widthMode = MeasureSpec.getMode(widthMeasureSpec);
896 if (widthMode != MeasureSpec.EXACTLY) {
897 throw new IllegalStateException(getClass().getSimpleName() + " can only be used " +
898 "with android:layout_width=\"match_parent\" (or fill_parent)");
901 int heightMode = MeasureSpec.getMode(heightMeasureSpec);
902 if (heightMode != MeasureSpec.AT_MOST) {
903 throw new IllegalStateException(getClass().getSimpleName() + " can only be used " +
904 "with android:layout_height=\"wrap_content\"");
907 int contentWidth = MeasureSpec.getSize(widthMeasureSpec);
909 int maxHeight = mContentHeight > 0 ?
910 mContentHeight : MeasureSpec.getSize(heightMeasureSpec);
912 final int verticalPadding = getPaddingTop() + getPaddingBottom();
913 final int paddingLeft = getPaddingLeft();
914 final int paddingRight = getPaddingRight();
915 final int height = maxHeight - verticalPadding;
916 final int childSpecHeight = MeasureSpec.makeMeasureSpec(height, MeasureSpec.AT_MOST);
918 int availableWidth = contentWidth - paddingLeft - paddingRight;
919 int leftOfCenter = availableWidth / 2;
920 int rightOfCenter = leftOfCenter;
922 HomeView homeLayout = mExpandedActionView != null ? mExpandedHomeLayout : mHomeLayout;
924 if (homeLayout.getVisibility() != GONE) {
925 final ViewGroup.LayoutParams lp = homeLayout.getLayoutParams();
928 homeWidthSpec = MeasureSpec.makeMeasureSpec(availableWidth, MeasureSpec.AT_MOST);
930 homeWidthSpec = MeasureSpec.makeMeasureSpec(lp.width, MeasureSpec.EXACTLY);
932 homeLayout.measure(homeWidthSpec,
933 MeasureSpec.makeMeasureSpec(height, MeasureSpec.EXACTLY));
934 final int homeWidth = homeLayout.getMeasuredWidth() + homeLayout.getLeftOffset();
935 availableWidth = Math.max(0, availableWidth - homeWidth);
936 leftOfCenter = Math.max(0, availableWidth - homeWidth);
939 if (mMenuView != null && mMenuView.getParent() == this) {
940 availableWidth = measureChildView(mMenuView, availableWidth,
942 rightOfCenter = Math.max(0, rightOfCenter - mMenuView.getMeasuredWidth());
945 if (mIndeterminateProgressView != null &&
946 mIndeterminateProgressView.getVisibility() != GONE) {
947 availableWidth = measureChildView(mIndeterminateProgressView, availableWidth,
949 rightOfCenter = Math.max(0,
950 rightOfCenter - mIndeterminateProgressView.getMeasuredWidth());
953 final boolean showTitle = mTitleLayout != null && mTitleLayout.getVisibility() != GONE &&
954 (mDisplayOptions & ActionBar.DISPLAY_SHOW_TITLE) != 0;
956 if (mExpandedActionView == null) {
957 switch (mNavigationMode) {
958 case ActionBar.NAVIGATION_MODE_LIST:
959 if (mListNavLayout != null) {
960 final int itemPaddingSize = showTitle ? mItemPadding * 2 : mItemPadding;
961 availableWidth = Math.max(0, availableWidth - itemPaddingSize);
962 leftOfCenter = Math.max(0, leftOfCenter - itemPaddingSize);
963 mListNavLayout.measure(
964 MeasureSpec.makeMeasureSpec(availableWidth, MeasureSpec.AT_MOST),
965 MeasureSpec.makeMeasureSpec(height, MeasureSpec.EXACTLY));
966 final int listNavWidth = mListNavLayout.getMeasuredWidth();
967 availableWidth = Math.max(0, availableWidth - listNavWidth);
968 leftOfCenter = Math.max(0, leftOfCenter - listNavWidth);
971 case ActionBar.NAVIGATION_MODE_TABS:
972 if (mTabScrollView != null) {
973 final int itemPaddingSize = showTitle ? mItemPadding * 2 : mItemPadding;
974 availableWidth = Math.max(0, availableWidth - itemPaddingSize);
975 leftOfCenter = Math.max(0, leftOfCenter - itemPaddingSize);
976 mTabScrollView.measure(
977 MeasureSpec.makeMeasureSpec(availableWidth, MeasureSpec.AT_MOST),
978 MeasureSpec.makeMeasureSpec(height, MeasureSpec.EXACTLY));
979 final int tabWidth = mTabScrollView.getMeasuredWidth();
980 availableWidth = Math.max(0, availableWidth - tabWidth);
981 leftOfCenter = Math.max(0, leftOfCenter - tabWidth);
987 View customView = null;
988 if (mExpandedActionView != null) {
989 customView = mExpandedActionView;
990 } else if ((mDisplayOptions & ActionBar.DISPLAY_SHOW_CUSTOM) != 0 &&
991 mCustomNavView != null) {
992 customView = mCustomNavView;
995 if (customView != null) {
996 final ViewGroup.LayoutParams lp = generateLayoutParams(customView.getLayoutParams());
997 final ActionBar.LayoutParams ablp = lp instanceof ActionBar.LayoutParams ?
998 (ActionBar.LayoutParams) lp : null;
1000 int horizontalMargin = 0;
1001 int verticalMargin = 0;
1003 horizontalMargin = ablp.leftMargin + ablp.rightMargin;
1004 verticalMargin = ablp.topMargin + ablp.bottomMargin;
1007 // If the action bar is wrapping to its content height, don't allow a custom
1008 // view to MATCH_PARENT.
1009 int customNavHeightMode;
1010 if (mContentHeight <= 0) {
1011 customNavHeightMode = MeasureSpec.AT_MOST;
1013 customNavHeightMode = lp.height != LayoutParams.WRAP_CONTENT ?
1014 MeasureSpec.EXACTLY : MeasureSpec.AT_MOST;
1016 final int customNavHeight = Math.max(0,
1017 (lp.height >= 0 ? Math.min(lp.height, height) : height) - verticalMargin);
1019 final int customNavWidthMode = lp.width != LayoutParams.WRAP_CONTENT ?
1020 MeasureSpec.EXACTLY : MeasureSpec.AT_MOST;
1021 int customNavWidth = Math.max(0,
1022 (lp.width >= 0 ? Math.min(lp.width, availableWidth) : availableWidth)
1023 - horizontalMargin);
1024 final int hgrav = (ablp != null ? ablp.gravity : DEFAULT_CUSTOM_GRAVITY) &
1025 Gravity.HORIZONTAL_GRAVITY_MASK;
1027 // Centering a custom view is treated specially; we try to center within the whole
1028 // action bar rather than in the available space.
1029 if (hgrav == Gravity.CENTER_HORIZONTAL && lp.width == LayoutParams.MATCH_PARENT) {
1030 customNavWidth = Math.min(leftOfCenter, rightOfCenter) * 2;
1034 MeasureSpec.makeMeasureSpec(customNavWidth, customNavWidthMode),
1035 MeasureSpec.makeMeasureSpec(customNavHeight, customNavHeightMode));
1036 availableWidth -= horizontalMargin + customView.getMeasuredWidth();
1039 if (mExpandedActionView == null && showTitle) {
1040 availableWidth = measureChildView(mTitleLayout, availableWidth,
1041 MeasureSpec.makeMeasureSpec(mContentHeight, MeasureSpec.EXACTLY), 0);
1042 leftOfCenter = Math.max(0, leftOfCenter - mTitleLayout.getMeasuredWidth());
1045 if (mContentHeight <= 0) {
1046 int measuredHeight = 0;
1047 for (int i = 0; i < childCount; i++) {
1048 View v = getChildAt(i);
1049 int paddedViewHeight = v.getMeasuredHeight() + verticalPadding;
1050 if (paddedViewHeight > measuredHeight) {
1051 measuredHeight = paddedViewHeight;
1054 setMeasuredDimension(contentWidth, measuredHeight);
1056 setMeasuredDimension(contentWidth, maxHeight);
1059 if (mContextView != null) {
1060 mContextView.setContentHeight(getMeasuredHeight());
1063 if (mProgressView != null && mProgressView.getVisibility() != GONE) {
1064 mProgressView.measure(MeasureSpec.makeMeasureSpec(
1065 contentWidth - mProgressBarPadding * 2, MeasureSpec.EXACTLY),
1066 MeasureSpec.makeMeasureSpec(getMeasuredHeight(), MeasureSpec.AT_MOST));
1071 protected void onLayout(boolean changed, int l, int t, int r, int b) {
1072 int x = getPaddingLeft();
1073 final int y = getPaddingTop();
1074 final int contentHeight = b - t - getPaddingTop() - getPaddingBottom();
1076 if (contentHeight <= 0) {
1077 // Nothing to do if we can't see anything.
1081 HomeView homeLayout = mExpandedActionView != null ? mExpandedHomeLayout : mHomeLayout;
1082 if (homeLayout.getVisibility() != GONE) {
1083 final int leftOffset = homeLayout.getLeftOffset();
1084 x += positionChild(homeLayout, x + leftOffset, y, contentHeight) + leftOffset;
1087 if (mExpandedActionView == null) {
1088 final boolean showTitle = mTitleLayout != null && mTitleLayout.getVisibility() != GONE &&
1089 (mDisplayOptions & ActionBar.DISPLAY_SHOW_TITLE) != 0;
1091 x += positionChild(mTitleLayout, x, y, contentHeight);
1094 switch (mNavigationMode) {
1095 case ActionBar.NAVIGATION_MODE_STANDARD:
1097 case ActionBar.NAVIGATION_MODE_LIST:
1098 if (mListNavLayout != null) {
1099 if (showTitle) x += mItemPadding;
1100 x += positionChild(mListNavLayout, x, y, contentHeight) + mItemPadding;
1103 case ActionBar.NAVIGATION_MODE_TABS:
1104 if (mTabScrollView != null) {
1105 if (showTitle) x += mItemPadding;
1106 x += positionChild(mTabScrollView, x, y, contentHeight) + mItemPadding;
1112 int menuLeft = r - l - getPaddingRight();
1113 if (mMenuView != null && mMenuView.getParent() == this) {
1114 positionChildInverse(mMenuView, menuLeft, y, contentHeight);
1115 menuLeft -= mMenuView.getMeasuredWidth();
1118 if (mIndeterminateProgressView != null &&
1119 mIndeterminateProgressView.getVisibility() != GONE) {
1120 positionChildInverse(mIndeterminateProgressView, menuLeft, y, contentHeight);
1121 menuLeft -= mIndeterminateProgressView.getMeasuredWidth();
1124 View customView = null;
1125 if (mExpandedActionView != null) {
1126 customView = mExpandedActionView;
1127 } else if ((mDisplayOptions & ActionBar.DISPLAY_SHOW_CUSTOM) != 0 &&
1128 mCustomNavView != null) {
1129 customView = mCustomNavView;
1131 if (customView != null) {
1132 ViewGroup.LayoutParams lp = customView.getLayoutParams();
1133 final ActionBar.LayoutParams ablp = lp instanceof ActionBar.LayoutParams ?
1134 (ActionBar.LayoutParams) lp : null;
1136 final int gravity = ablp != null ? ablp.gravity : DEFAULT_CUSTOM_GRAVITY;
1137 final int navWidth = customView.getMeasuredWidth();
1140 int bottomMargin = 0;
1142 x += ablp.leftMargin;
1143 menuLeft -= ablp.rightMargin;
1144 topMargin = ablp.topMargin;
1145 bottomMargin = ablp.bottomMargin;
1148 int hgravity = gravity & Gravity.HORIZONTAL_GRAVITY_MASK;
1149 // See if we actually have room to truly center; if not push against left or right.
1150 if (hgravity == Gravity.CENTER_HORIZONTAL) {
1151 final int centeredLeft = ((getRight() - getLeft()) - navWidth) / 2;
1152 if (centeredLeft < x) {
1153 hgravity = Gravity.LEFT;
1154 } else if (centeredLeft + navWidth > menuLeft) {
1155 hgravity = Gravity.RIGHT;
1157 } else if (gravity == -1) {
1158 hgravity = Gravity.LEFT;
1163 case Gravity.CENTER_HORIZONTAL:
1164 xpos = ((getRight() - getLeft()) - navWidth) / 2;
1170 xpos = menuLeft - navWidth;
1174 int vgravity = gravity & Gravity.VERTICAL_GRAVITY_MASK;
1176 if (gravity == -1) {
1177 vgravity = Gravity.CENTER_VERTICAL;
1182 case Gravity.CENTER_VERTICAL:
1183 final int paddedTop = getPaddingTop();
1184 final int paddedBottom = getBottom() - getTop() - getPaddingBottom();
1185 ypos = ((paddedBottom - paddedTop) - customView.getMeasuredHeight()) / 2;
1188 ypos = getPaddingTop() + topMargin;
1190 case Gravity.BOTTOM:
1191 ypos = getHeight() - getPaddingBottom() - customView.getMeasuredHeight()
1195 final int customWidth = customView.getMeasuredWidth();
1196 customView.layout(xpos, ypos, xpos + customWidth,
1197 ypos + customView.getMeasuredHeight());
1201 if (mProgressView != null) {
1202 mProgressView.bringToFront();
1203 final int halfProgressHeight = mProgressView.getMeasuredHeight() / 2;
1204 mProgressView.layout(mProgressBarPadding, -halfProgressHeight,
1205 mProgressBarPadding + mProgressView.getMeasuredWidth(), halfProgressHeight);
1210 public ViewGroup.LayoutParams generateLayoutParams(AttributeSet attrs) {
1211 return new ActionBar.LayoutParams(getContext(), attrs);
1215 public ViewGroup.LayoutParams generateLayoutParams(ViewGroup.LayoutParams lp) {
1217 lp = generateDefaultLayoutParams();
1223 public Parcelable onSaveInstanceState() {
1224 Parcelable superState = super.onSaveInstanceState();
1225 SavedState state = new SavedState(superState);
1227 if (mExpandedMenuPresenter != null && mExpandedMenuPresenter.mCurrentExpandedItem != null) {
1228 state.expandedMenuItemId = mExpandedMenuPresenter.mCurrentExpandedItem.getItemId();
1231 state.isOverflowOpen = isOverflowMenuShowing();
1237 public void onRestoreInstanceState(Parcelable p) {
1238 SavedState state = (SavedState) p;
1240 super.onRestoreInstanceState(state.getSuperState());
1242 if (state.expandedMenuItemId != 0 &&
1243 mExpandedMenuPresenter != null && mOptionsMenu != null) {
1244 final MenuItem item = mOptionsMenu.findItem(state.expandedMenuItemId);
1246 item.expandActionView();
1250 if (state.isOverflowOpen) {
1251 postShowOverflowMenu();
1255 static class SavedState extends BaseSavedState {
1256 int expandedMenuItemId;
1257 boolean isOverflowOpen;
1259 SavedState(Parcelable superState) {
1263 private SavedState(Parcel in) {
1265 expandedMenuItemId = in.readInt();
1266 isOverflowOpen = in.readInt() != 0;
1270 public void writeToParcel(Parcel out, int flags) {
1271 super.writeToParcel(out, flags);
1272 out.writeInt(expandedMenuItemId);
1273 out.writeInt(isOverflowOpen ? 1 : 0);
1276 public static final Parcelable.Creator<SavedState> CREATOR =
1277 new Parcelable.Creator<SavedState>() {
1278 public SavedState createFromParcel(Parcel in) {
1279 return new SavedState(in);
1282 public SavedState[] newArray(int size) {
1283 return new SavedState[size];
1288 public static class HomeView extends FrameLayout {
1289 private View mUpView;
1290 private ImageView mIconView;
1291 private int mUpWidth;
1293 public HomeView(Context context) {
1294 this(context, null);
1297 public HomeView(Context context, AttributeSet attrs) {
1298 super(context, attrs);
1301 public void setUp(boolean isUp) {
1302 mUpView.setVisibility(isUp ? VISIBLE : GONE);
1305 public void setIcon(Drawable icon) {
1306 mIconView.setImageDrawable(icon);
1310 public boolean dispatchPopulateAccessibilityEvent(AccessibilityEvent event) {
1311 onPopulateAccessibilityEvent(event);
1316 public void onPopulateAccessibilityEvent(AccessibilityEvent event) {
1317 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH) {
1318 super.onPopulateAccessibilityEvent(event);
1320 final CharSequence cdesc = getContentDescription();
1321 if (!TextUtils.isEmpty(cdesc)) {
1322 event.getText().add(cdesc);
1327 public boolean dispatchHoverEvent(MotionEvent event) {
1328 // Don't allow children to hover; we want this to be treated as a single component.
1329 return onHoverEvent(event);
1333 protected void onFinishInflate() {
1334 mUpView = findViewById(R.id.abs__up);
1335 mIconView = (ImageView) findViewById(R.id.abs__home);
1338 public int getLeftOffset() {
1339 return mUpView.getVisibility() == GONE ? mUpWidth : 0;
1343 protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
1344 measureChildWithMargins(mUpView, widthMeasureSpec, 0, heightMeasureSpec, 0);
1345 final LayoutParams upLp = (LayoutParams) mUpView.getLayoutParams();
1346 mUpWidth = upLp.leftMargin + mUpView.getMeasuredWidth() + upLp.rightMargin;
1347 int width = mUpView.getVisibility() == GONE ? 0 : mUpWidth;
1348 int height = upLp.topMargin + mUpView.getMeasuredHeight() + upLp.bottomMargin;
1349 measureChildWithMargins(mIconView, widthMeasureSpec, width, heightMeasureSpec, 0);
1350 final LayoutParams iconLp = (LayoutParams) mIconView.getLayoutParams();
1351 width += iconLp.leftMargin + mIconView.getMeasuredWidth() + iconLp.rightMargin;
1352 height = Math.max(height,
1353 iconLp.topMargin + mIconView.getMeasuredHeight() + iconLp.bottomMargin);
1355 final int widthMode = MeasureSpec.getMode(widthMeasureSpec);
1356 final int heightMode = MeasureSpec.getMode(heightMeasureSpec);
1357 final int widthSize = MeasureSpec.getSize(widthMeasureSpec);
1358 final int heightSize = MeasureSpec.getSize(heightMeasureSpec);
1360 switch (widthMode) {
1361 case MeasureSpec.AT_MOST:
1362 width = Math.min(width, widthSize);
1364 case MeasureSpec.EXACTLY:
1367 case MeasureSpec.UNSPECIFIED:
1371 switch (heightMode) {
1372 case MeasureSpec.AT_MOST:
1373 height = Math.min(height, heightSize);
1375 case MeasureSpec.EXACTLY:
1376 height = heightSize;
1378 case MeasureSpec.UNSPECIFIED:
1382 setMeasuredDimension(width, height);
1386 protected void onLayout(boolean changed, int l, int t, int r, int b) {
1387 final int vCenter = (b - t) / 2;
1388 //UNUSED int width = r - l;
1390 if (mUpView.getVisibility() != GONE) {
1391 final LayoutParams upLp = (LayoutParams) mUpView.getLayoutParams();
1392 final int upHeight = mUpView.getMeasuredHeight();
1393 final int upWidth = mUpView.getMeasuredWidth();
1394 final int upTop = vCenter - upHeight / 2;
1395 mUpView.layout(0, upTop, upWidth, upTop + upHeight);
1396 upOffset = upLp.leftMargin + upWidth + upLp.rightMargin;
1397 //UNUSED width -= upOffset;
1400 final LayoutParams iconLp = (LayoutParams) mIconView.getLayoutParams();
1401 final int iconHeight = mIconView.getMeasuredHeight();
1402 final int iconWidth = mIconView.getMeasuredWidth();
1403 final int hCenter = (r - l) / 2;
1404 final int iconLeft = upOffset + Math.max(iconLp.leftMargin, hCenter - iconWidth / 2);
1405 final int iconTop = Math.max(iconLp.topMargin, vCenter - iconHeight / 2);
1406 mIconView.layout(iconLeft, iconTop, iconLeft + iconWidth, iconTop + iconHeight);
1410 private class ExpandedActionViewMenuPresenter implements MenuPresenter {
1412 MenuItemImpl mCurrentExpandedItem;
1415 public void initForMenu(Context context, MenuBuilder menu) {
1416 // Clear the expanded action view when menus change.
1417 if (mMenu != null && mCurrentExpandedItem != null) {
1418 mMenu.collapseItemActionView(mCurrentExpandedItem);
1424 public MenuView getMenuView(ViewGroup root) {
1429 public void updateMenuView(boolean cleared) {
1430 // Make sure the expanded item we have is still there.
1431 if (mCurrentExpandedItem != null) {
1432 boolean found = false;
1434 if (mMenu != null) {
1435 final int count = mMenu.size();
1436 for (int i = 0; i < count; i++) {
1437 final MenuItem item = mMenu.getItem(i);
1438 if (item == mCurrentExpandedItem) {
1446 // The item we had expanded disappeared. Collapse.
1447 collapseItemActionView(mMenu, mCurrentExpandedItem);
1453 public void setCallback(Callback cb) {
1457 public boolean onSubMenuSelected(SubMenuBuilder subMenu) {
1462 public void onCloseMenu(MenuBuilder menu, boolean allMenusAreClosing) {
1466 public boolean flagActionItems() {
1471 public boolean expandItemActionView(MenuBuilder menu, MenuItemImpl item) {
1472 mExpandedActionView = item.getActionView();
1473 mExpandedHomeLayout.setIcon(mIcon.getConstantState().newDrawable(/* TODO getResources() */));
1474 mCurrentExpandedItem = item;
1475 if (mExpandedActionView.getParent() != ActionBarView.this) {
1476 addView(mExpandedActionView);
1478 if (mExpandedHomeLayout.getParent() != ActionBarView.this) {
1479 addView(mExpandedHomeLayout);
1481 mHomeLayout.setVisibility(GONE);
1482 if (mTitleLayout != null) mTitleLayout.setVisibility(GONE);
1483 if (mTabScrollView != null) mTabScrollView.setVisibility(GONE);
1484 if (mSpinner != null) mSpinner.setVisibility(GONE);
1485 if (mCustomNavView != null) mCustomNavView.setVisibility(GONE);
1487 item.setActionViewExpanded(true);
1489 if (mExpandedActionView instanceof CollapsibleActionView) {
1490 ((CollapsibleActionView) mExpandedActionView).onActionViewExpanded();
1497 public boolean collapseItemActionView(MenuBuilder menu, MenuItemImpl item) {
1498 // Do this before detaching the actionview from the hierarchy, in case
1499 // it needs to dismiss the soft keyboard, etc.
1500 if (mExpandedActionView instanceof CollapsibleActionView) {
1501 ((CollapsibleActionView) mExpandedActionView).onActionViewCollapsed();
1504 removeView(mExpandedActionView);
1505 removeView(mExpandedHomeLayout);
1506 mExpandedActionView = null;
1507 if ((mDisplayOptions & ActionBar.DISPLAY_SHOW_HOME) != 0) {
1508 mHomeLayout.setVisibility(VISIBLE);
1510 if ((mDisplayOptions & ActionBar.DISPLAY_SHOW_TITLE) != 0) {
1511 if (mTitleLayout == null) {
1514 mTitleLayout.setVisibility(VISIBLE);
1517 if (mTabScrollView != null && mNavigationMode == ActionBar.NAVIGATION_MODE_TABS) {
1518 mTabScrollView.setVisibility(VISIBLE);
1520 if (mSpinner != null && mNavigationMode == ActionBar.NAVIGATION_MODE_LIST) {
1521 mSpinner.setVisibility(VISIBLE);
1523 if (mCustomNavView != null && (mDisplayOptions & ActionBar.DISPLAY_SHOW_CUSTOM) != 0) {
1524 mCustomNavView.setVisibility(VISIBLE);
1526 mExpandedHomeLayout.setIcon(null);
1527 mCurrentExpandedItem = null;
1529 item.setActionViewExpanded(false);
1535 public int getId() {
1540 public Parcelable onSaveInstanceState() {
1545 public void onRestoreInstanceState(Parcelable state) {