ActionBarView.java revision 894bf54c0f50dbbaeb737842a89516a3029e233a
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 17package com.android.internal.widget; 18 19import com.android.internal.R; 20import com.android.internal.view.menu.ActionMenuItem; 21import com.android.internal.view.menu.ActionMenuPresenter; 22import com.android.internal.view.menu.ActionMenuView; 23import com.android.internal.view.menu.MenuBuilder; 24import com.android.internal.view.menu.MenuItemImpl; 25import com.android.internal.view.menu.MenuPresenter; 26import com.android.internal.view.menu.MenuView; 27import com.android.internal.view.menu.SubMenuBuilder; 28 29import android.app.ActionBar; 30import android.app.ActionBar.OnNavigationListener; 31import android.app.Activity; 32import android.content.Context; 33import android.content.pm.ApplicationInfo; 34import android.content.pm.PackageManager; 35import android.content.pm.PackageManager.NameNotFoundException; 36import android.content.res.Resources; 37import android.content.res.TypedArray; 38import android.graphics.drawable.Drawable; 39import android.os.Parcel; 40import android.os.Parcelable; 41import android.text.TextUtils; 42import android.util.AttributeSet; 43import android.util.DisplayMetrics; 44import android.util.Log; 45import android.view.CollapsibleActionView; 46import android.view.Gravity; 47import android.view.LayoutInflater; 48import android.view.Menu; 49import android.view.MenuItem; 50import android.view.View; 51import android.view.ViewGroup; 52import android.view.ViewParent; 53import android.view.Window; 54import android.widget.AdapterView; 55import android.widget.FrameLayout; 56import android.widget.ImageView; 57import android.widget.LinearLayout; 58import android.widget.ProgressBar; 59import android.widget.Spinner; 60import android.widget.SpinnerAdapter; 61import android.widget.TextView; 62 63/** 64 * @hide 65 */ 66public class ActionBarView extends AbsActionBarView { 67 private static final String TAG = "ActionBarView"; 68 69 /** 70 * Display options applied by default 71 */ 72 public static final int DISPLAY_DEFAULT = 0; 73 74 /** 75 * Display options that require re-layout as opposed to a simple invalidate 76 */ 77 private static final int DISPLAY_RELAYOUT_MASK = 78 ActionBar.DISPLAY_SHOW_HOME | 79 ActionBar.DISPLAY_USE_LOGO | 80 ActionBar.DISPLAY_HOME_AS_UP | 81 ActionBar.DISPLAY_SHOW_CUSTOM | 82 ActionBar.DISPLAY_SHOW_TITLE; 83 84 private static final int DEFAULT_CUSTOM_GRAVITY = Gravity.LEFT | Gravity.CENTER_VERTICAL; 85 86 private int mContentHeight; 87 88 private int mNavigationMode; 89 private int mDisplayOptions = ActionBar.DISPLAY_SHOW_HOME | ActionBar.DISPLAY_HOME_AS_UP; 90 private CharSequence mTitle; 91 private CharSequence mSubtitle; 92 private Drawable mIcon; 93 private Drawable mLogo; 94 95 private HomeView mHomeLayout; 96 private HomeView mExpandedHomeLayout; 97 private LinearLayout mTitleLayout; 98 private TextView mTitleView; 99 private TextView mSubtitleView; 100 private View mTitleUpView; 101 102 private Spinner mSpinner; 103 private LinearLayout mListNavLayout; 104 private ScrollingTabContainerView mTabScrollView; 105 private View mCustomNavView; 106 private ProgressBar mProgressView; 107 private ProgressBar mIndeterminateProgressView; 108 109 private int mProgressBarPadding; 110 private int mItemPadding; 111 112 private int mTitleStyleRes; 113 private int mSubtitleStyleRes; 114 private int mProgressStyle; 115 private int mIndeterminateProgressStyle; 116 117 private boolean mSplitActionBar; 118 private boolean mUserTitle; 119 private boolean mIncludeTabs; 120 private boolean mIsCollapsable; 121 private boolean mIsCollapsed; 122 123 private MenuBuilder mOptionsMenu; 124 125 private ActionBarContextView mContextView; 126 127 private ActionMenuItem mLogoNavItem; 128 129 private SpinnerAdapter mSpinnerAdapter; 130 private OnNavigationListener mCallback; 131 132 private Runnable mTabSelector; 133 134 private ExpandedActionViewMenuPresenter mExpandedMenuPresenter; 135 View mExpandedActionView; 136 137 private final AdapterView.OnItemSelectedListener mNavItemSelectedListener = 138 new AdapterView.OnItemSelectedListener() { 139 public void onItemSelected(AdapterView parent, View view, int position, long id) { 140 if (mCallback != null) { 141 mCallback.onNavigationItemSelected(position, id); 142 } 143 } 144 public void onNothingSelected(AdapterView parent) { 145 // Do nothing 146 } 147 }; 148 149 private final OnClickListener mExpandedActionViewUpListener = new OnClickListener() { 150 @Override 151 public void onClick(View v) { 152 final MenuItemImpl item = mExpandedMenuPresenter.mCurrentExpandedItem; 153 if (item != null) { 154 item.collapseActionView(); 155 } 156 } 157 }; 158 159 private final OnClickListener mUpClickListener = new OnClickListener() { 160 public void onClick(View v) { 161 Context context = getContext(); 162 if (context instanceof Activity) { 163 Activity activity = (Activity) context; 164 activity.onMenuItemSelected(Window.FEATURE_OPTIONS_PANEL, mLogoNavItem); 165 } 166 } 167 }; 168 169 public ActionBarView(Context context, AttributeSet attrs) { 170 super(context, attrs); 171 172 // Background is always provided by the container. 173 setBackgroundResource(0); 174 175 TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.ActionBar); 176 177 ApplicationInfo appInfo = context.getApplicationInfo(); 178 PackageManager pm = context.getPackageManager(); 179 mNavigationMode = a.getInt(R.styleable.ActionBar_navigationMode, 180 ActionBar.NAVIGATION_MODE_STANDARD); 181 mTitle = a.getText(R.styleable.ActionBar_title); 182 mSubtitle = a.getText(R.styleable.ActionBar_subtitle); 183 184 mLogo = a.getDrawable(R.styleable.ActionBar_logo); 185 if (mLogo == null) { 186 if (context instanceof Activity) { 187 try { 188 mLogo = pm.getActivityLogo(((Activity) context).getComponentName()); 189 } catch (NameNotFoundException e) { 190 Log.e(TAG, "Activity component name not found!", e); 191 } 192 } 193 if (mLogo == null) { 194 mLogo = appInfo.loadLogo(pm); 195 } 196 } 197 198 mIcon = a.getDrawable(R.styleable.ActionBar_icon); 199 if (mIcon == null) { 200 if (context instanceof Activity) { 201 try { 202 mIcon = pm.getActivityIcon(((Activity) context).getComponentName()); 203 } catch (NameNotFoundException e) { 204 Log.e(TAG, "Activity component name not found!", e); 205 } 206 } 207 if (mIcon == null) { 208 mIcon = appInfo.loadIcon(pm); 209 } 210 } 211 212 final LayoutInflater inflater = LayoutInflater.from(context); 213 214 final int homeResId = a.getResourceId( 215 com.android.internal.R.styleable.ActionBar_homeLayout, 216 com.android.internal.R.layout.action_bar_home); 217 218 mHomeLayout = (HomeView) inflater.inflate(homeResId, this, false); 219 220 mExpandedHomeLayout = (HomeView) inflater.inflate(homeResId, this, false); 221 mExpandedHomeLayout.setUp(true); 222 mExpandedHomeLayout.setOnClickListener(mExpandedActionViewUpListener); 223 224 mTitleStyleRes = a.getResourceId(R.styleable.ActionBar_titleTextStyle, 0); 225 mSubtitleStyleRes = a.getResourceId(R.styleable.ActionBar_subtitleTextStyle, 0); 226 mProgressStyle = a.getResourceId(R.styleable.ActionBar_progressBarStyle, 0); 227 mIndeterminateProgressStyle = a.getResourceId( 228 R.styleable.ActionBar_indeterminateProgressStyle, 0); 229 230 mProgressBarPadding = a.getDimensionPixelOffset(R.styleable.ActionBar_progressBarPadding, 0); 231 mItemPadding = a.getDimensionPixelOffset(R.styleable.ActionBar_itemPadding, 0); 232 233 setDisplayOptions(a.getInt(R.styleable.ActionBar_displayOptions, DISPLAY_DEFAULT)); 234 235 final int customNavId = a.getResourceId(R.styleable.ActionBar_customNavigationLayout, 0); 236 if (customNavId != 0) { 237 mCustomNavView = (View) inflater.inflate(customNavId, this, false); 238 mNavigationMode = ActionBar.NAVIGATION_MODE_STANDARD; 239 setDisplayOptions(mDisplayOptions | ActionBar.DISPLAY_SHOW_CUSTOM); 240 } 241 242 mContentHeight = a.getLayoutDimension(R.styleable.ActionBar_height, 0); 243 244 a.recycle(); 245 246 mLogoNavItem = new ActionMenuItem(context, 0, android.R.id.home, 0, 0, mTitle); 247 mHomeLayout.setOnClickListener(mUpClickListener); 248 mHomeLayout.setClickable(true); 249 mHomeLayout.setFocusable(true); 250 } 251 252 @Override 253 public void onDetachedFromWindow() { 254 super.onDetachedFromWindow(); 255 removeCallbacks(mTabSelector); 256 } 257 258 @Override 259 public boolean shouldDelayChildPressedState() { 260 return false; 261 } 262 263 public void initProgress() { 264 mProgressView = new ProgressBar(mContext, null, 0, mProgressStyle); 265 mProgressView.setId(R.id.progress_horizontal); 266 mProgressView.setMax(10000); 267 addView(mProgressView); 268 } 269 270 public void initIndeterminateProgress() { 271 mIndeterminateProgressView = new ProgressBar(mContext, null, 0, 272 mIndeterminateProgressStyle); 273 mIndeterminateProgressView.setId(R.id.progress_circular); 274 addView(mIndeterminateProgressView); 275 } 276 277 public void setContentHeight(int height) { 278 mContentHeight = height; 279 requestLayout(); 280 } 281 282 public int getContentHeight() { 283 return mContentHeight; 284 } 285 286 public void setSplitActionBar(boolean splitActionBar) { 287 if (mSplitActionBar != splitActionBar) { 288 if (mMenuView != null) { 289 final ViewGroup oldParent = (ViewGroup) mMenuView.getParent(); 290 if (oldParent != null) { 291 oldParent.removeView(mMenuView); 292 } 293 if (splitActionBar) { 294 if (mSplitView != null) { 295 mSplitView.addView(mMenuView); 296 } 297 } else { 298 addView(mMenuView); 299 } 300 } 301 mSplitActionBar = splitActionBar; 302 } 303 } 304 305 public boolean isSplitActionBar() { 306 return mSplitActionBar; 307 } 308 309 public boolean hasEmbeddedTabs() { 310 return mIncludeTabs; 311 } 312 313 public void setEmbeddedTabView(ScrollingTabContainerView tabs) { 314 if (mTabScrollView != null) { 315 removeView(mTabScrollView); 316 } 317 mTabScrollView = tabs; 318 mIncludeTabs = tabs != null; 319 if (mIncludeTabs && mNavigationMode == ActionBar.NAVIGATION_MODE_TABS) { 320 addView(mTabScrollView); 321 } 322 } 323 324 public void setCallback(OnNavigationListener callback) { 325 mCallback = callback; 326 } 327 328 public void setMenu(Menu menu, MenuPresenter.Callback cb) { 329 if (menu == mOptionsMenu) return; 330 331 if (mOptionsMenu != null) { 332 mOptionsMenu.removeMenuPresenter(mActionMenuPresenter); 333 mOptionsMenu.removeMenuPresenter(mExpandedMenuPresenter); 334 } 335 336 MenuBuilder builder = (MenuBuilder) menu; 337 mOptionsMenu = builder; 338 if (mMenuView != null) { 339 final ViewGroup oldParent = (ViewGroup) mMenuView.getParent(); 340 if (oldParent != null) { 341 oldParent.removeView(mMenuView); 342 } 343 } 344 if (mActionMenuPresenter == null) { 345 mActionMenuPresenter = new ActionMenuPresenter(); 346 mActionMenuPresenter.setCallback(cb); 347 mActionMenuPresenter.setId(com.android.internal.R.id.action_menu_presenter); 348 mExpandedMenuPresenter = new ExpandedActionViewMenuPresenter(); 349 } 350 351 ActionMenuView menuView; 352 final LayoutParams layoutParams = new LayoutParams(LayoutParams.WRAP_CONTENT, 353 LayoutParams.MATCH_PARENT); 354 if (!mSplitActionBar) { 355 mActionMenuPresenter.setExpandedActionViewsExclusive( 356 getResources().getBoolean( 357 com.android.internal.R.bool.action_bar_expanded_action_views_exclusive)); 358 builder.addMenuPresenter(mActionMenuPresenter); 359 builder.addMenuPresenter(mExpandedMenuPresenter); 360 menuView = (ActionMenuView) mActionMenuPresenter.getMenuView(this); 361 final ViewGroup oldParent = (ViewGroup) menuView.getParent(); 362 if (oldParent != null && oldParent != this) { 363 oldParent.removeView(menuView); 364 } 365 addView(menuView, layoutParams); 366 } else { 367 mActionMenuPresenter.setExpandedActionViewsExclusive(false); 368 // Allow full screen width in split mode. 369 mActionMenuPresenter.setWidthLimit( 370 getContext().getResources().getDisplayMetrics().widthPixels, true); 371 // No limit to the item count; use whatever will fit. 372 mActionMenuPresenter.setItemLimit(Integer.MAX_VALUE); 373 // Span the whole width 374 layoutParams.width = LayoutParams.MATCH_PARENT; 375 builder.addMenuPresenter(mActionMenuPresenter); 376 builder.addMenuPresenter(mExpandedMenuPresenter); 377 menuView = (ActionMenuView) mActionMenuPresenter.getMenuView(this); 378 if (mSplitView != null) { 379 final ViewGroup oldParent = (ViewGroup) menuView.getParent(); 380 if (oldParent != null && oldParent != mSplitView) { 381 oldParent.removeView(menuView); 382 } 383 mSplitView.addView(menuView, layoutParams); 384 } else { 385 // We'll add this later if we missed it this time. 386 menuView.setLayoutParams(layoutParams); 387 } 388 } 389 mMenuView = menuView; 390 } 391 392 public boolean hasExpandedActionView() { 393 return mExpandedMenuPresenter != null && 394 mExpandedMenuPresenter.mCurrentExpandedItem != null; 395 } 396 397 public void collapseActionView() { 398 final MenuItemImpl item = mExpandedMenuPresenter == null ? null : 399 mExpandedMenuPresenter.mCurrentExpandedItem; 400 if (item != null) { 401 item.collapseActionView(); 402 } 403 } 404 405 public void setCustomNavigationView(View view) { 406 final boolean showCustom = (mDisplayOptions & ActionBar.DISPLAY_SHOW_CUSTOM) != 0; 407 if (mCustomNavView != null && showCustom) { 408 removeView(mCustomNavView); 409 } 410 mCustomNavView = view; 411 if (mCustomNavView != null && showCustom) { 412 addView(mCustomNavView); 413 } 414 } 415 416 public CharSequence getTitle() { 417 return mTitle; 418 } 419 420 /** 421 * Set the action bar title. This will always replace or override window titles. 422 * @param title Title to set 423 * 424 * @see #setWindowTitle(CharSequence) 425 */ 426 public void setTitle(CharSequence title) { 427 mUserTitle = true; 428 setTitleImpl(title); 429 } 430 431 /** 432 * Set the window title. A window title will always be replaced or overridden by a user title. 433 * @param title Title to set 434 * 435 * @see #setTitle(CharSequence) 436 */ 437 public void setWindowTitle(CharSequence title) { 438 if (!mUserTitle) { 439 setTitleImpl(title); 440 } 441 } 442 443 private void setTitleImpl(CharSequence title) { 444 mTitle = title; 445 if (mTitleView != null) { 446 mTitleView.setText(title); 447 mTitleLayout.setVisibility(TextUtils.isEmpty(mTitle) && TextUtils.isEmpty(mSubtitle) ? 448 GONE : VISIBLE); 449 } 450 if (mLogoNavItem != null) { 451 mLogoNavItem.setTitle(title); 452 } 453 } 454 455 public CharSequence getSubtitle() { 456 return mSubtitle; 457 } 458 459 public void setSubtitle(CharSequence subtitle) { 460 mSubtitle = subtitle; 461 if (mSubtitleView != null) { 462 mSubtitleView.setText(subtitle); 463 mSubtitleView.setVisibility(subtitle != null ? VISIBLE : GONE); 464 mTitleLayout.setVisibility(TextUtils.isEmpty(mTitle) && TextUtils.isEmpty(mSubtitle) ? 465 GONE : VISIBLE); 466 } 467 } 468 469 public void setHomeButtonEnabled(boolean enable) { 470 mHomeLayout.setEnabled(enable); 471 // Make sure the home button has an accurate content description for accessibility. 472 if (!enable) { 473 mHomeLayout.setContentDescription(null); 474 } else if ((mDisplayOptions & ActionBar.DISPLAY_HOME_AS_UP) != 0) { 475 mHomeLayout.setContentDescription(mContext.getResources().getText( 476 R.string.action_bar_up_description)); 477 } else { 478 mHomeLayout.setContentDescription(mContext.getResources().getText( 479 R.string.action_bar_home_description)); 480 } 481 } 482 483 public void setDisplayOptions(int options) { 484 final int flagsChanged = options ^ mDisplayOptions; 485 mDisplayOptions = options; 486 487 if ((flagsChanged & DISPLAY_RELAYOUT_MASK) != 0) { 488 final boolean showHome = (options & ActionBar.DISPLAY_SHOW_HOME) != 0; 489 final int vis = showHome ? VISIBLE : GONE; 490 mHomeLayout.setVisibility(vis); 491 492 if ((flagsChanged & ActionBar.DISPLAY_HOME_AS_UP) != 0) { 493 final boolean setUp = (options & ActionBar.DISPLAY_HOME_AS_UP) != 0; 494 mHomeLayout.setUp(setUp); 495 496 // Showing home as up implicitly enables interaction with it. 497 // In honeycomb it was always enabled, so make this transition 498 // a bit easier for developers in the common case. 499 // (It would be silly to show it as up without responding to it.) 500 if (setUp) { 501 setHomeButtonEnabled(true); 502 } 503 } 504 505 if ((flagsChanged & ActionBar.DISPLAY_USE_LOGO) != 0) { 506 final boolean logoVis = mLogo != null && (options & ActionBar.DISPLAY_USE_LOGO) != 0; 507 mHomeLayout.setIcon(logoVis ? mLogo : mIcon); 508 } 509 510 if ((flagsChanged & ActionBar.DISPLAY_SHOW_TITLE) != 0) { 511 if ((options & ActionBar.DISPLAY_SHOW_TITLE) != 0) { 512 initTitle(); 513 } else { 514 removeView(mTitleLayout); 515 } 516 } 517 518 if (mTitleLayout != null && (flagsChanged & 519 (ActionBar.DISPLAY_HOME_AS_UP | ActionBar.DISPLAY_SHOW_HOME)) != 0) { 520 final boolean homeAsUp = (options & ActionBar.DISPLAY_HOME_AS_UP) != 0; 521 final boolean titleUp = homeAsUp && !showHome; 522 mTitleUpView.setVisibility(titleUp ? VISIBLE : GONE); 523 mTitleLayout.setEnabled(titleUp); 524 } 525 526 if ((flagsChanged & ActionBar.DISPLAY_SHOW_CUSTOM) != 0 && mCustomNavView != null) { 527 if ((options & ActionBar.DISPLAY_SHOW_CUSTOM) != 0) { 528 addView(mCustomNavView); 529 } else { 530 removeView(mCustomNavView); 531 } 532 } 533 534 requestLayout(); 535 } else { 536 invalidate(); 537 } 538 539 // Make sure the home button has an accurate content description for accessibility. 540 if (!mHomeLayout.isEnabled()) { 541 mHomeLayout.setContentDescription(null); 542 } else if ((options & ActionBar.DISPLAY_HOME_AS_UP) != 0) { 543 mHomeLayout.setContentDescription(mContext.getResources().getText( 544 R.string.action_bar_up_description)); 545 } else { 546 mHomeLayout.setContentDescription(mContext.getResources().getText( 547 R.string.action_bar_home_description)); 548 } 549 } 550 551 public void setIcon(Drawable icon) { 552 mIcon = icon; 553 if (icon != null && 554 ((mDisplayOptions & ActionBar.DISPLAY_USE_LOGO) == 0 || mLogo == null)) { 555 mHomeLayout.setIcon(icon); 556 } 557 } 558 559 public void setIcon(int resId) { 560 setIcon(mContext.getResources().getDrawableForDensity(resId, getPreferredIconDensity())); 561 } 562 563 public void setLogo(Drawable logo) { 564 mLogo = logo; 565 if (logo != null && (mDisplayOptions & ActionBar.DISPLAY_USE_LOGO) != 0) { 566 mHomeLayout.setIcon(logo); 567 } 568 } 569 570 public void setLogo(int resId) { 571 mContext.getResources().getDrawable(resId); 572 } 573 574 /** 575 * @return Drawable density to load that will best fit the available height. 576 */ 577 private int getPreferredIconDensity() { 578 final Resources res = mContext.getResources(); 579 final int availableHeight = getLayoutParams().height - 580 mHomeLayout.getVerticalIconPadding(); 581 int iconSize = res.getDimensionPixelSize(android.R.dimen.app_icon_size); 582 583 if (iconSize * DisplayMetrics.DENSITY_LOW >= availableHeight) { 584 return DisplayMetrics.DENSITY_LOW; 585 } else if (iconSize * DisplayMetrics.DENSITY_MEDIUM >= availableHeight) { 586 return DisplayMetrics.DENSITY_MEDIUM; 587 } else if (iconSize * DisplayMetrics.DENSITY_HIGH >= availableHeight) { 588 return DisplayMetrics.DENSITY_HIGH; 589 } 590 return DisplayMetrics.DENSITY_XHIGH; 591 } 592 593 public void setNavigationMode(int mode) { 594 final int oldMode = mNavigationMode; 595 if (mode != oldMode) { 596 switch (oldMode) { 597 case ActionBar.NAVIGATION_MODE_LIST: 598 if (mListNavLayout != null) { 599 removeView(mListNavLayout); 600 } 601 break; 602 case ActionBar.NAVIGATION_MODE_TABS: 603 if (mTabScrollView != null && mIncludeTabs) { 604 removeView(mTabScrollView); 605 } 606 } 607 608 switch (mode) { 609 case ActionBar.NAVIGATION_MODE_LIST: 610 if (mSpinner == null) { 611 mSpinner = new Spinner(mContext, null, 612 com.android.internal.R.attr.actionDropDownStyle); 613 mListNavLayout = new LinearLayout(mContext, null, 614 com.android.internal.R.attr.actionBarTabBarStyle); 615 LinearLayout.LayoutParams params = new LinearLayout.LayoutParams( 616 LayoutParams.WRAP_CONTENT, LayoutParams.MATCH_PARENT); 617 params.gravity = Gravity.CENTER; 618 mListNavLayout.addView(mSpinner, params); 619 } 620 if (mSpinner.getAdapter() != mSpinnerAdapter) { 621 mSpinner.setAdapter(mSpinnerAdapter); 622 } 623 mSpinner.setOnItemSelectedListener(mNavItemSelectedListener); 624 addView(mListNavLayout); 625 break; 626 case ActionBar.NAVIGATION_MODE_TABS: 627 if (mTabScrollView != null && mIncludeTabs) { 628 addView(mTabScrollView); 629 } 630 break; 631 } 632 mNavigationMode = mode; 633 requestLayout(); 634 } 635 } 636 637 public ScrollingTabContainerView createTabContainer() { 638 final LinearLayout tabLayout = new LinearLayout(getContext(), null, 639 com.android.internal.R.attr.actionBarTabBarStyle); 640 tabLayout.setMeasureWithLargestChildEnabled(true); 641 tabLayout.setLayoutParams(new LinearLayout.LayoutParams( 642 LinearLayout.LayoutParams.WRAP_CONTENT, mContentHeight)); 643 644 final ScrollingTabContainerView scroller = new ScrollingTabContainerView(mContext); 645 scroller.setTabLayout(tabLayout); 646 return scroller; 647 } 648 649 public void setDropdownAdapter(SpinnerAdapter adapter) { 650 mSpinnerAdapter = adapter; 651 if (mSpinner != null) { 652 mSpinner.setAdapter(adapter); 653 } 654 } 655 656 public SpinnerAdapter getDropdownAdapter() { 657 return mSpinnerAdapter; 658 } 659 660 public void setDropdownSelectedPosition(int position) { 661 mSpinner.setSelection(position); 662 } 663 664 public int getDropdownSelectedPosition() { 665 return mSpinner.getSelectedItemPosition(); 666 } 667 668 public View getCustomNavigationView() { 669 return mCustomNavView; 670 } 671 672 public int getNavigationMode() { 673 return mNavigationMode; 674 } 675 676 public int getDisplayOptions() { 677 return mDisplayOptions; 678 } 679 680 @Override 681 protected LayoutParams generateDefaultLayoutParams() { 682 // Used by custom nav views if they don't supply layout params. Everything else 683 // added to an ActionBarView should have them already. 684 return new ActionBar.LayoutParams(DEFAULT_CUSTOM_GRAVITY); 685 } 686 687 @Override 688 protected void onFinishInflate() { 689 super.onFinishInflate(); 690 691 addView(mHomeLayout); 692 693 if (mCustomNavView != null && (mDisplayOptions & ActionBar.DISPLAY_SHOW_CUSTOM) != 0) { 694 final ViewParent parent = mCustomNavView.getParent(); 695 if (parent != this) { 696 if (parent instanceof ViewGroup) { 697 ((ViewGroup) parent).removeView(mCustomNavView); 698 } 699 addView(mCustomNavView); 700 } 701 } 702 } 703 704 private void initTitle() { 705 if (mTitleLayout == null) { 706 LayoutInflater inflater = LayoutInflater.from(getContext()); 707 mTitleLayout = (LinearLayout) inflater.inflate(R.layout.action_bar_title_item, null); 708 mTitleView = (TextView) mTitleLayout.findViewById(R.id.action_bar_title); 709 mSubtitleView = (TextView) mTitleLayout.findViewById(R.id.action_bar_subtitle); 710 mTitleUpView = (View) mTitleLayout.findViewById(R.id.up); 711 712 mTitleLayout.setOnClickListener(mUpClickListener); 713 714 if (mTitleStyleRes != 0) { 715 mTitleView.setTextAppearance(mContext, mTitleStyleRes); 716 } 717 if (mTitle != null) { 718 mTitleView.setText(mTitle); 719 } 720 721 if (mSubtitleStyleRes != 0) { 722 mSubtitleView.setTextAppearance(mContext, mSubtitleStyleRes); 723 } 724 if (mSubtitle != null) { 725 mSubtitleView.setText(mSubtitle); 726 mSubtitleView.setVisibility(VISIBLE); 727 } 728 729 final boolean homeAsUp = (mDisplayOptions & ActionBar.DISPLAY_HOME_AS_UP) != 0; 730 final boolean titleUp = homeAsUp && 731 (mDisplayOptions & ActionBar.DISPLAY_SHOW_HOME) == 0; 732 mTitleUpView.setVisibility(titleUp ? VISIBLE : GONE); 733 mTitleLayout.setEnabled(titleUp); 734 } 735 736 addView(mTitleLayout); 737 } 738 739 public void setContextView(ActionBarContextView view) { 740 mContextView = view; 741 } 742 743 public void setCollapsable(boolean collapsable) { 744 mIsCollapsable = collapsable; 745 } 746 747 public boolean isCollapsed() { 748 return mIsCollapsed; 749 } 750 751 @Override 752 protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { 753 final int childCount = getChildCount(); 754 if (mIsCollapsable) { 755 int visibleChildren = 0; 756 for (int i = 0; i < childCount; i++) { 757 final View child = getChildAt(i); 758 if (child.getVisibility() != GONE && 759 !(child == mMenuView && mMenuView.getChildCount() == 0)) { 760 visibleChildren++; 761 } 762 } 763 764 if (visibleChildren == 0) { 765 // No size for an empty action bar when collapsable. 766 setMeasuredDimension(0, 0); 767 mIsCollapsed = true; 768 return; 769 } 770 } 771 mIsCollapsed = false; 772 773 int widthMode = MeasureSpec.getMode(widthMeasureSpec); 774 if (widthMode != MeasureSpec.EXACTLY) { 775 throw new IllegalStateException(getClass().getSimpleName() + " can only be used " + 776 "with android:layout_width=\"match_parent\" (or fill_parent)"); 777 } 778 779 int heightMode = MeasureSpec.getMode(heightMeasureSpec); 780 if (heightMode != MeasureSpec.AT_MOST) { 781 throw new IllegalStateException(getClass().getSimpleName() + " can only be used " + 782 "with android:layout_height=\"wrap_content\""); 783 } 784 785 int contentWidth = MeasureSpec.getSize(widthMeasureSpec); 786 787 int maxHeight = mContentHeight > 0 ? 788 mContentHeight : MeasureSpec.getSize(heightMeasureSpec); 789 790 final int verticalPadding = getPaddingTop() + getPaddingBottom(); 791 final int paddingLeft = getPaddingLeft(); 792 final int paddingRight = getPaddingRight(); 793 final int height = maxHeight - verticalPadding; 794 final int childSpecHeight = MeasureSpec.makeMeasureSpec(height, MeasureSpec.AT_MOST); 795 796 int availableWidth = contentWidth - paddingLeft - paddingRight; 797 int leftOfCenter = availableWidth / 2; 798 int rightOfCenter = leftOfCenter; 799 800 View homeLayout = mExpandedActionView != null ? mExpandedHomeLayout : mHomeLayout; 801 802 if (homeLayout.getVisibility() != GONE) { 803 final LayoutParams lp = homeLayout.getLayoutParams(); 804 int homeWidthSpec; 805 if (lp.width < 0) { 806 homeWidthSpec = MeasureSpec.makeMeasureSpec(availableWidth, MeasureSpec.AT_MOST); 807 } else { 808 homeWidthSpec = MeasureSpec.makeMeasureSpec(lp.width, MeasureSpec.EXACTLY); 809 } 810 homeLayout.measure(homeWidthSpec, 811 MeasureSpec.makeMeasureSpec(height, MeasureSpec.EXACTLY)); 812 final int homeWidth = homeLayout.getMeasuredWidth(); 813 availableWidth = Math.max(0, availableWidth - homeWidth); 814 leftOfCenter = Math.max(0, availableWidth - homeWidth); 815 } 816 817 if (mMenuView != null && mMenuView.getParent() == this) { 818 availableWidth = measureChildView(mMenuView, availableWidth, 819 childSpecHeight, 0); 820 rightOfCenter = Math.max(0, rightOfCenter - mMenuView.getMeasuredWidth()); 821 } 822 823 if (mExpandedActionView == null) { 824 boolean showTitle = mTitleLayout != null && mTitleLayout.getVisibility() != GONE && 825 (mDisplayOptions & ActionBar.DISPLAY_SHOW_TITLE) != 0; 826 if (showTitle) { 827 availableWidth = measureChildView(mTitleLayout, availableWidth, childSpecHeight, 0); 828 leftOfCenter = Math.max(0, leftOfCenter - mTitleLayout.getMeasuredWidth()); 829 } 830 831 switch (mNavigationMode) { 832 case ActionBar.NAVIGATION_MODE_LIST: 833 if (mListNavLayout != null) { 834 final int itemPaddingSize = showTitle ? mItemPadding * 2 : mItemPadding; 835 availableWidth = Math.max(0, availableWidth - itemPaddingSize); 836 leftOfCenter = Math.max(0, leftOfCenter - itemPaddingSize); 837 mListNavLayout.measure( 838 MeasureSpec.makeMeasureSpec(availableWidth, MeasureSpec.AT_MOST), 839 MeasureSpec.makeMeasureSpec(height, MeasureSpec.EXACTLY)); 840 final int listNavWidth = mListNavLayout.getMeasuredWidth(); 841 availableWidth = Math.max(0, availableWidth - listNavWidth); 842 leftOfCenter = Math.max(0, leftOfCenter - listNavWidth); 843 } 844 break; 845 case ActionBar.NAVIGATION_MODE_TABS: 846 if (mTabScrollView != null) { 847 final int itemPaddingSize = showTitle ? mItemPadding * 2 : mItemPadding; 848 availableWidth = Math.max(0, availableWidth - itemPaddingSize); 849 leftOfCenter = Math.max(0, leftOfCenter - itemPaddingSize); 850 mTabScrollView.measure( 851 MeasureSpec.makeMeasureSpec(availableWidth, MeasureSpec.AT_MOST), 852 MeasureSpec.makeMeasureSpec(height, MeasureSpec.EXACTLY)); 853 final int tabWidth = mTabScrollView.getMeasuredWidth(); 854 availableWidth = Math.max(0, availableWidth - tabWidth); 855 leftOfCenter = Math.max(0, leftOfCenter - tabWidth); 856 } 857 break; 858 } 859 } 860 861 if (mIndeterminateProgressView != null && 862 mIndeterminateProgressView.getVisibility() != GONE) { 863 availableWidth = measureChildView(mIndeterminateProgressView, availableWidth, 864 childSpecHeight, 0); 865 rightOfCenter = Math.max(0, 866 rightOfCenter - mIndeterminateProgressView.getMeasuredWidth()); 867 } 868 869 View customView = null; 870 if (mExpandedActionView != null) { 871 customView = mExpandedActionView; 872 } else if ((mDisplayOptions & ActionBar.DISPLAY_SHOW_CUSTOM) != 0 && 873 mCustomNavView != null) { 874 customView = mCustomNavView; 875 } 876 877 if (customView != null) { 878 final LayoutParams lp = generateLayoutParams(customView.getLayoutParams()); 879 final ActionBar.LayoutParams ablp = lp instanceof ActionBar.LayoutParams ? 880 (ActionBar.LayoutParams) lp : null; 881 882 int horizontalMargin = 0; 883 int verticalMargin = 0; 884 if (ablp != null) { 885 horizontalMargin = ablp.leftMargin + ablp.rightMargin; 886 verticalMargin = ablp.topMargin + ablp.bottomMargin; 887 } 888 889 // If the action bar is wrapping to its content height, don't allow a custom 890 // view to MATCH_PARENT. 891 int customNavHeightMode; 892 if (mContentHeight <= 0) { 893 customNavHeightMode = MeasureSpec.AT_MOST; 894 } else { 895 customNavHeightMode = lp.height != LayoutParams.WRAP_CONTENT ? 896 MeasureSpec.EXACTLY : MeasureSpec.AT_MOST; 897 } 898 final int customNavHeight = Math.max(0, 899 (lp.height >= 0 ? Math.min(lp.height, height) : height) - verticalMargin); 900 901 final int customNavWidthMode = lp.width != LayoutParams.WRAP_CONTENT ? 902 MeasureSpec.EXACTLY : MeasureSpec.AT_MOST; 903 int customNavWidth = Math.max(0, 904 (lp.width >= 0 ? Math.min(lp.width, availableWidth) : availableWidth) 905 - horizontalMargin); 906 final int hgrav = (ablp != null ? ablp.gravity : DEFAULT_CUSTOM_GRAVITY) & 907 Gravity.HORIZONTAL_GRAVITY_MASK; 908 909 // Centering a custom view is treated specially; we try to center within the whole 910 // action bar rather than in the available space. 911 if (hgrav == Gravity.CENTER_HORIZONTAL && lp.width == LayoutParams.MATCH_PARENT) { 912 customNavWidth = Math.min(leftOfCenter, rightOfCenter) * 2; 913 } 914 915 customView.measure( 916 MeasureSpec.makeMeasureSpec(customNavWidth, customNavWidthMode), 917 MeasureSpec.makeMeasureSpec(customNavHeight, customNavHeightMode)); 918 } 919 920 if (mContentHeight <= 0) { 921 int measuredHeight = 0; 922 for (int i = 0; i < childCount; i++) { 923 View v = getChildAt(i); 924 int paddedViewHeight = v.getMeasuredHeight() + verticalPadding; 925 if (paddedViewHeight > measuredHeight) { 926 measuredHeight = paddedViewHeight; 927 } 928 } 929 setMeasuredDimension(contentWidth, measuredHeight); 930 } else { 931 setMeasuredDimension(contentWidth, maxHeight); 932 } 933 934 if (mContextView != null) { 935 mContextView.setHeight(getMeasuredHeight()); 936 } 937 938 if (mProgressView != null && mProgressView.getVisibility() != GONE) { 939 mProgressView.measure(MeasureSpec.makeMeasureSpec( 940 contentWidth - mProgressBarPadding * 2, MeasureSpec.EXACTLY), 941 MeasureSpec.makeMeasureSpec(getMeasuredHeight(), MeasureSpec.AT_MOST)); 942 } 943 } 944 945 @Override 946 protected void onLayout(boolean changed, int l, int t, int r, int b) { 947 int x = getPaddingLeft(); 948 final int y = getPaddingTop(); 949 final int contentHeight = b - t - getPaddingTop() - getPaddingBottom(); 950 951 if (contentHeight <= 0) { 952 // Nothing to do if we can't see anything. 953 return; 954 } 955 956 View homeLayout = mExpandedActionView != null ? mExpandedHomeLayout : mHomeLayout; 957 if (homeLayout.getVisibility() != GONE) { 958 x += positionChild(homeLayout, x, y, contentHeight); 959 } 960 961 if (mExpandedActionView == null) { 962 final boolean showTitle = mTitleLayout != null && mTitleLayout.getVisibility() != GONE && 963 (mDisplayOptions & ActionBar.DISPLAY_SHOW_TITLE) != 0; 964 if (showTitle) { 965 x += positionChild(mTitleLayout, x, y, contentHeight); 966 } 967 968 switch (mNavigationMode) { 969 case ActionBar.NAVIGATION_MODE_STANDARD: 970 break; 971 case ActionBar.NAVIGATION_MODE_LIST: 972 if (mListNavLayout != null) { 973 if (showTitle) x += mItemPadding; 974 x += positionChild(mListNavLayout, x, y, contentHeight) + mItemPadding; 975 } 976 break; 977 case ActionBar.NAVIGATION_MODE_TABS: 978 if (mTabScrollView != null) { 979 if (showTitle) x += mItemPadding; 980 x += positionChild(mTabScrollView, x, y, contentHeight) + mItemPadding; 981 } 982 break; 983 } 984 } 985 986 int menuLeft = r - l - getPaddingRight(); 987 if (mMenuView != null && mMenuView.getParent() == this) { 988 positionChildInverse(mMenuView, menuLeft, y, contentHeight); 989 menuLeft -= mMenuView.getMeasuredWidth(); 990 } 991 992 if (mIndeterminateProgressView != null && 993 mIndeterminateProgressView.getVisibility() != GONE) { 994 positionChildInverse(mIndeterminateProgressView, menuLeft, y, contentHeight); 995 menuLeft -= mIndeterminateProgressView.getMeasuredWidth(); 996 } 997 998 View customView = null; 999 if (mExpandedActionView != null) { 1000 customView = mExpandedActionView; 1001 } else if ((mDisplayOptions & ActionBar.DISPLAY_SHOW_CUSTOM) != 0 && 1002 mCustomNavView != null) { 1003 customView = mCustomNavView; 1004 } 1005 if (customView != null) { 1006 LayoutParams lp = customView.getLayoutParams(); 1007 final ActionBar.LayoutParams ablp = lp instanceof ActionBar.LayoutParams ? 1008 (ActionBar.LayoutParams) lp : null; 1009 1010 final int gravity = ablp != null ? ablp.gravity : DEFAULT_CUSTOM_GRAVITY; 1011 final int navWidth = customView.getMeasuredWidth(); 1012 1013 int topMargin = 0; 1014 int bottomMargin = 0; 1015 if (ablp != null) { 1016 x += ablp.leftMargin; 1017 menuLeft -= ablp.rightMargin; 1018 topMargin = ablp.topMargin; 1019 bottomMargin = ablp.bottomMargin; 1020 } 1021 1022 int hgravity = gravity & Gravity.HORIZONTAL_GRAVITY_MASK; 1023 // See if we actually have room to truly center; if not push against left or right. 1024 if (hgravity == Gravity.CENTER_HORIZONTAL) { 1025 final int centeredLeft = ((mRight - mLeft) - navWidth) / 2; 1026 if (centeredLeft < x) { 1027 hgravity = Gravity.LEFT; 1028 } else if (centeredLeft + navWidth > menuLeft) { 1029 hgravity = Gravity.RIGHT; 1030 } 1031 } 1032 1033 int xpos = 0; 1034 switch (hgravity) { 1035 case Gravity.CENTER_HORIZONTAL: 1036 xpos = ((mRight - mLeft) - navWidth) / 2; 1037 break; 1038 case Gravity.LEFT: 1039 xpos = x; 1040 break; 1041 case Gravity.RIGHT: 1042 xpos = menuLeft - navWidth; 1043 break; 1044 } 1045 1046 int ypos = 0; 1047 switch (gravity & Gravity.VERTICAL_GRAVITY_MASK) { 1048 case Gravity.CENTER_VERTICAL: 1049 final int paddedTop = getPaddingTop(); 1050 final int paddedBottom = mBottom - mTop - getPaddingBottom(); 1051 ypos = ((paddedBottom - paddedTop) - customView.getMeasuredHeight()) / 2; 1052 break; 1053 case Gravity.TOP: 1054 ypos = getPaddingTop() + topMargin; 1055 break; 1056 case Gravity.BOTTOM: 1057 ypos = getHeight() - getPaddingBottom() - customView.getMeasuredHeight() 1058 - bottomMargin; 1059 break; 1060 } 1061 final int customWidth = customView.getMeasuredWidth(); 1062 customView.layout(xpos, ypos, xpos + customWidth, 1063 ypos + customView.getMeasuredHeight()); 1064 x += customWidth; 1065 } 1066 1067 if (mProgressView != null) { 1068 mProgressView.bringToFront(); 1069 final int halfProgressHeight = mProgressView.getMeasuredHeight() / 2; 1070 mProgressView.layout(mProgressBarPadding, -halfProgressHeight, 1071 mProgressBarPadding + mProgressView.getMeasuredWidth(), halfProgressHeight); 1072 } 1073 } 1074 1075 @Override 1076 public LayoutParams generateLayoutParams(LayoutParams lp) { 1077 if (lp == null) { 1078 lp = generateDefaultLayoutParams(); 1079 } 1080 return lp; 1081 } 1082 1083 @Override 1084 public Parcelable onSaveInstanceState() { 1085 Parcelable superState = super.onSaveInstanceState(); 1086 SavedState state = new SavedState(superState); 1087 1088 if (mExpandedMenuPresenter != null && mExpandedMenuPresenter.mCurrentExpandedItem != null) { 1089 state.expandedMenuItemId = mExpandedMenuPresenter.mCurrentExpandedItem.getItemId(); 1090 } 1091 1092 state.isOverflowOpen = isOverflowMenuShowing(); 1093 1094 return state; 1095 } 1096 1097 @Override 1098 public void onRestoreInstanceState(Parcelable p) { 1099 SavedState state = (SavedState) p; 1100 1101 super.onRestoreInstanceState(state.getSuperState()); 1102 1103 if (state.expandedMenuItemId != 0 && 1104 mExpandedMenuPresenter != null && mOptionsMenu != null) { 1105 final MenuItem item = mOptionsMenu.findItem(state.expandedMenuItemId); 1106 if (item != null) { 1107 item.expandActionView(); 1108 } 1109 } 1110 1111 if (state.isOverflowOpen) { 1112 postShowOverflowMenu(); 1113 } 1114 } 1115 1116 static class SavedState extends BaseSavedState { 1117 int expandedMenuItemId; 1118 boolean isOverflowOpen; 1119 1120 SavedState(Parcelable superState) { 1121 super(superState); 1122 } 1123 1124 private SavedState(Parcel in) { 1125 super(in); 1126 expandedMenuItemId = in.readInt(); 1127 isOverflowOpen = in.readInt() != 0; 1128 } 1129 1130 @Override 1131 public void writeToParcel(Parcel out, int flags) { 1132 super.writeToParcel(out, flags); 1133 out.writeInt(expandedMenuItemId); 1134 out.writeInt(isOverflowOpen ? 1 : 0); 1135 } 1136 1137 public static final Parcelable.Creator<SavedState> CREATOR = 1138 new Parcelable.Creator<SavedState>() { 1139 public SavedState createFromParcel(Parcel in) { 1140 return new SavedState(in); 1141 } 1142 1143 public SavedState[] newArray(int size) { 1144 return new SavedState[size]; 1145 } 1146 }; 1147 } 1148 1149 private static class HomeView extends FrameLayout { 1150 private View mUpView; 1151 private ImageView mIconView; 1152 1153 public HomeView(Context context) { 1154 this(context, null); 1155 } 1156 1157 public HomeView(Context context, AttributeSet attrs) { 1158 super(context, attrs); 1159 } 1160 1161 public void setUp(boolean isUp) { 1162 mUpView.setVisibility(isUp ? VISIBLE : GONE); 1163 } 1164 1165 public void setIcon(Drawable icon) { 1166 mIconView.setImageDrawable(icon); 1167 } 1168 1169 @Override 1170 protected void onFinishInflate() { 1171 mUpView = findViewById(com.android.internal.R.id.up); 1172 mIconView = (ImageView) findViewById(com.android.internal.R.id.home); 1173 } 1174 1175 public int getVerticalIconPadding() { 1176 return mIconView.getPaddingTop() + mIconView.getPaddingBottom(); 1177 } 1178 1179 @Override 1180 protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { 1181 measureChildWithMargins(mUpView, widthMeasureSpec, 0, heightMeasureSpec, 0); 1182 final LayoutParams upLp = (LayoutParams) mUpView.getLayoutParams(); 1183 int width = upLp.leftMargin + mUpView.getMeasuredWidth() + upLp.rightMargin; 1184 int height = upLp.topMargin + mUpView.getMeasuredHeight() + upLp.bottomMargin; 1185 measureChildWithMargins(mIconView, widthMeasureSpec, width, heightMeasureSpec, 0); 1186 final LayoutParams iconLp = (LayoutParams) mIconView.getLayoutParams(); 1187 width += iconLp.leftMargin + mIconView.getMeasuredWidth() + iconLp.rightMargin; 1188 height = Math.max(height, 1189 iconLp.topMargin + mIconView.getMeasuredHeight() + iconLp.bottomMargin); 1190 1191 final int widthMode = MeasureSpec.getMode(widthMeasureSpec); 1192 final int heightMode = MeasureSpec.getMode(heightMeasureSpec); 1193 final int widthSize = MeasureSpec.getSize(widthMeasureSpec); 1194 final int heightSize = MeasureSpec.getSize(heightMeasureSpec); 1195 1196 switch (widthMode) { 1197 case MeasureSpec.AT_MOST: 1198 width = Math.min(width, widthSize); 1199 break; 1200 case MeasureSpec.EXACTLY: 1201 width = widthSize; 1202 break; 1203 case MeasureSpec.UNSPECIFIED: 1204 default: 1205 break; 1206 } 1207 switch (heightMode) { 1208 case MeasureSpec.AT_MOST: 1209 height = Math.min(height, heightSize); 1210 break; 1211 case MeasureSpec.EXACTLY: 1212 height = heightSize; 1213 break; 1214 case MeasureSpec.UNSPECIFIED: 1215 default: 1216 break; 1217 } 1218 setMeasuredDimension(width, height); 1219 } 1220 1221 @Override 1222 protected void onLayout(boolean changed, int l, int t, int r, int b) { 1223 final int vCenter = (b - t) / 2; 1224 int width = r - l; 1225 int upOffset = 0; 1226 if (mUpView.getVisibility() != GONE) { 1227 final LayoutParams upLp = (LayoutParams) mUpView.getLayoutParams(); 1228 final int upHeight = mUpView.getMeasuredHeight(); 1229 final int upWidth = mUpView.getMeasuredWidth(); 1230 final int upTop = vCenter - upHeight / 2; 1231 mUpView.layout(0, upTop, upWidth, upTop + upHeight); 1232 upOffset = upLp.leftMargin + upWidth + upLp.rightMargin; 1233 width -= upOffset; 1234 l += upOffset; 1235 } 1236 final LayoutParams iconLp = (LayoutParams) mIconView.getLayoutParams(); 1237 final int iconHeight = mIconView.getMeasuredHeight(); 1238 final int iconWidth = mIconView.getMeasuredWidth(); 1239 final int hCenter = (r - l) / 2; 1240 final int iconLeft = upOffset + Math.max(iconLp.leftMargin, hCenter - iconWidth / 2); 1241 final int iconTop = Math.max(iconLp.topMargin, vCenter - iconHeight / 2); 1242 mIconView.layout(iconLeft, iconTop, iconLeft + iconWidth, iconTop + iconHeight); 1243 } 1244 } 1245 1246 private class ExpandedActionViewMenuPresenter implements MenuPresenter { 1247 MenuBuilder mMenu; 1248 MenuItemImpl mCurrentExpandedItem; 1249 1250 @Override 1251 public void initForMenu(Context context, MenuBuilder menu) { 1252 // Clear the expanded action view when menus change. 1253 mExpandedActionView = null; 1254 if (mCurrentExpandedItem != null) { 1255 mCurrentExpandedItem.collapseActionView(); 1256 } 1257 mMenu = menu; 1258 } 1259 1260 @Override 1261 public MenuView getMenuView(ViewGroup root) { 1262 return null; 1263 } 1264 1265 @Override 1266 public void updateMenuView(boolean cleared) { 1267 // Make sure the expanded item we have is still there. 1268 if (mCurrentExpandedItem != null) { 1269 boolean found = false; 1270 final int count = mMenu.size(); 1271 for (int i = 0; i < count; i++) { 1272 final MenuItem item = mMenu.getItem(i); 1273 if (item == mCurrentExpandedItem) { 1274 found = true; 1275 break; 1276 } 1277 } 1278 1279 if (!found) { 1280 // The item we had expanded disappeared. Collapse. 1281 collapseItemActionView(mMenu, mCurrentExpandedItem); 1282 } 1283 } 1284 } 1285 1286 @Override 1287 public void setCallback(Callback cb) { 1288 } 1289 1290 @Override 1291 public boolean onSubMenuSelected(SubMenuBuilder subMenu) { 1292 return false; 1293 } 1294 1295 @Override 1296 public void onCloseMenu(MenuBuilder menu, boolean allMenusAreClosing) { 1297 } 1298 1299 @Override 1300 public boolean flagActionItems() { 1301 return false; 1302 } 1303 1304 @Override 1305 public boolean expandItemActionView(MenuBuilder menu, MenuItemImpl item) { 1306 mExpandedActionView = item.getActionView(); 1307 mExpandedHomeLayout.setIcon(mIcon.getConstantState().newDrawable(getResources())); 1308 mCurrentExpandedItem = item; 1309 if (mExpandedActionView.getParent() != ActionBarView.this) { 1310 addView(mExpandedActionView); 1311 } 1312 if (mExpandedHomeLayout.getParent() != ActionBarView.this) { 1313 addView(mExpandedHomeLayout); 1314 } 1315 mHomeLayout.setVisibility(GONE); 1316 if (mTitleLayout != null) mTitleLayout.setVisibility(GONE); 1317 if (mTabScrollView != null) mTabScrollView.setVisibility(GONE); 1318 if (mSpinner != null) mSpinner.setVisibility(GONE); 1319 if (mCustomNavView != null) mCustomNavView.setVisibility(GONE); 1320 requestLayout(); 1321 item.setActionViewExpanded(true); 1322 1323 if (mExpandedActionView instanceof CollapsibleActionView) { 1324 ((CollapsibleActionView) mExpandedActionView).onActionViewExpanded(); 1325 } 1326 return true; 1327 } 1328 1329 @Override 1330 public boolean collapseItemActionView(MenuBuilder menu, MenuItemImpl item) { 1331 removeView(mExpandedActionView); 1332 removeView(mExpandedHomeLayout); 1333 if ((mDisplayOptions & ActionBar.DISPLAY_SHOW_HOME) != 0) { 1334 mHomeLayout.setVisibility(VISIBLE); 1335 } 1336 if ((mDisplayOptions & ActionBar.DISPLAY_SHOW_TITLE) != 0) { 1337 if (mTitleLayout == null) { 1338 initTitle(); 1339 } else { 1340 mTitleLayout.setVisibility(VISIBLE); 1341 } 1342 } 1343 if (mTabScrollView != null && mNavigationMode == ActionBar.NAVIGATION_MODE_TABS) { 1344 mTabScrollView.setVisibility(VISIBLE); 1345 } 1346 if (mSpinner != null && mNavigationMode == ActionBar.NAVIGATION_MODE_LIST) { 1347 mSpinner.setVisibility(VISIBLE); 1348 } 1349 if (mCustomNavView != null && (mDisplayOptions & ActionBar.DISPLAY_SHOW_CUSTOM) != 0) { 1350 mCustomNavView.setVisibility(VISIBLE); 1351 } 1352 View collapsedView = mExpandedActionView; 1353 mExpandedActionView = null; 1354 mExpandedHomeLayout.setIcon(null); 1355 mCurrentExpandedItem = null; 1356 requestLayout(); 1357 item.setActionViewExpanded(false); 1358 1359 if (collapsedView instanceof CollapsibleActionView) { 1360 ((CollapsibleActionView) collapsedView).onActionViewCollapsed(); 1361 } 1362 return true; 1363 } 1364 1365 @Override 1366 public int getId() { 1367 return 0; 1368 } 1369 1370 @Override 1371 public Parcelable onSaveInstanceState() { 1372 return null; 1373 } 1374 1375 @Override 1376 public void onRestoreInstanceState(Parcelable state) { 1377 } 1378 } 1379} 1380