ActionBarImpl.java revision f6ce6a9bacbb220c6ea7b552c481237f23e64ae7
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.app; 18 19import com.android.internal.view.menu.MenuBuilder; 20import com.android.internal.view.menu.MenuPopupHelper; 21import com.android.internal.view.menu.SubMenuBuilder; 22import com.android.internal.widget.ActionBarContainer; 23import com.android.internal.widget.ActionBarContextView; 24import com.android.internal.widget.ActionBarView; 25import com.android.internal.widget.ScrollingTabContainerView; 26 27import android.animation.Animator; 28import android.animation.Animator.AnimatorListener; 29import android.animation.AnimatorListenerAdapter; 30import android.animation.AnimatorSet; 31import android.animation.ObjectAnimator; 32import android.app.ActionBar; 33import android.app.Activity; 34import android.app.Dialog; 35import android.app.FragmentTransaction; 36import android.content.Context; 37import android.content.res.Configuration; 38import android.graphics.drawable.Drawable; 39import android.os.Handler; 40import android.view.ActionMode; 41import android.view.LayoutInflater; 42import android.view.Menu; 43import android.view.MenuInflater; 44import android.view.MenuItem; 45import android.view.View; 46import android.view.Window; 47import android.widget.SpinnerAdapter; 48 49import java.lang.ref.WeakReference; 50import java.util.ArrayList; 51 52/** 53 * ActionBarImpl is the ActionBar implementation used 54 * by devices of all screen sizes. If it detects a compatible decor, 55 * it will split contextual modes across both the ActionBarView at 56 * the top of the screen and a horizontal LinearLayout at the bottom 57 * which is normally hidden. 58 */ 59public class ActionBarImpl extends ActionBar { 60 private static final String TAG = "ActionBarImpl"; 61 62 private Context mContext; 63 private Activity mActivity; 64 private Dialog mDialog; 65 66 private ActionBarContainer mContainerView; 67 private ActionBarView mActionView; 68 private ActionBarContextView mContextView; 69 private ActionBarContainer mSplitView; 70 private View mContentView; 71 private ScrollingTabContainerView mTabScrollView; 72 73 private ArrayList<TabImpl> mTabs = new ArrayList<TabImpl>(); 74 75 private TabImpl mSelectedTab; 76 private int mSavedTabPosition = INVALID_POSITION; 77 78 private ActionMode mActionMode; 79 80 private boolean mLastMenuVisibility; 81 private ArrayList<OnMenuVisibilityListener> mMenuVisibilityListeners = 82 new ArrayList<OnMenuVisibilityListener>(); 83 84 private static final int CONTEXT_DISPLAY_NORMAL = 0; 85 private static final int CONTEXT_DISPLAY_SPLIT = 1; 86 87 private static final int INVALID_POSITION = -1; 88 89 private int mContextDisplayMode; 90 private boolean mHasEmbeddedTabs; 91 private int mContentHeight; 92 93 final Handler mHandler = new Handler(); 94 Runnable mTabSelector; 95 96 private Animator mCurrentShowAnim; 97 private Animator mCurrentModeAnim; 98 private boolean mShowHideAnimationEnabled; 99 boolean mWasHiddenBeforeMode; 100 101 final AnimatorListener mHideListener = new AnimatorListenerAdapter() { 102 @Override 103 public void onAnimationEnd(Animator animation) { 104 if (mContentView != null) { 105 mContentView.setTranslationY(0); 106 } 107 mContainerView.setVisibility(View.GONE); 108 mContainerView.setTransitioning(false); 109 mCurrentShowAnim = null; 110 } 111 }; 112 113 final AnimatorListener mShowListener = new AnimatorListenerAdapter() { 114 @Override 115 public void onAnimationEnd(Animator animation) { 116 mCurrentShowAnim = null; 117 mContainerView.requestLayout(); 118 } 119 }; 120 121 public ActionBarImpl(Activity activity) { 122 mActivity = activity; 123 Window window = activity.getWindow(); 124 View decor = window.getDecorView(); 125 init(decor); 126 if (!mActivity.getWindow().hasFeature(Window.FEATURE_ACTION_BAR_OVERLAY)) { 127 mContentView = decor.findViewById(android.R.id.content); 128 } 129 } 130 131 public ActionBarImpl(Dialog dialog) { 132 mDialog = dialog; 133 init(dialog.getWindow().getDecorView()); 134 } 135 136 private void init(View decor) { 137 mContext = decor.getContext(); 138 mActionView = (ActionBarView) decor.findViewById(com.android.internal.R.id.action_bar); 139 mContextView = (ActionBarContextView) decor.findViewById( 140 com.android.internal.R.id.action_context_bar); 141 mContainerView = (ActionBarContainer) decor.findViewById( 142 com.android.internal.R.id.action_bar_container); 143 mSplitView = (ActionBarContainer) decor.findViewById( 144 com.android.internal.R.id.split_action_bar); 145 146 if (mActionView == null || mContextView == null || mContainerView == null) { 147 throw new IllegalStateException(getClass().getSimpleName() + " can only be used " + 148 "with a compatible window decor layout"); 149 } 150 151 mHasEmbeddedTabs = mContext.getResources().getBoolean( 152 com.android.internal.R.bool.action_bar_embed_tabs); 153 mActionView.setContextView(mContextView); 154 mContextDisplayMode = mActionView.isSplitActionBar() ? 155 CONTEXT_DISPLAY_SPLIT : CONTEXT_DISPLAY_NORMAL; 156 157 mContentHeight = mActionView.getContentHeight(); 158 } 159 160 public void onConfigurationChanged(Configuration newConfig) { 161 mHasEmbeddedTabs = mContext.getResources().getBoolean( 162 com.android.internal.R.bool.action_bar_embed_tabs); 163 164 // Switch tab layout configuration if needed 165 if (!mHasEmbeddedTabs) { 166 mActionView.setEmbeddedTabView(null); 167 mContainerView.setTabContainer(mTabScrollView); 168 } else { 169 mContainerView.setTabContainer(null); 170 if (mTabScrollView != null) { 171 mTabScrollView.setVisibility(View.VISIBLE); 172 } 173 mActionView.setEmbeddedTabView(mTabScrollView); 174 } 175 mActionView.setCollapsable(!mHasEmbeddedTabs && 176 getNavigationMode() == NAVIGATION_MODE_TABS); 177 178 mContentHeight = mActionView.getContentHeight(); 179 180 if (mTabScrollView != null) { 181 mTabScrollView.getLayoutParams().height = mContentHeight; 182 mTabScrollView.requestLayout(); 183 } 184 } 185 186 private void ensureTabsExist() { 187 if (mTabScrollView != null) { 188 return; 189 } 190 191 ScrollingTabContainerView tabScroller = mActionView.createTabContainer(); 192 193 if (mHasEmbeddedTabs) { 194 tabScroller.setVisibility(View.VISIBLE); 195 mActionView.setEmbeddedTabView(tabScroller); 196 } else { 197 tabScroller.setVisibility(getNavigationMode() == NAVIGATION_MODE_TABS ? 198 View.VISIBLE : View.GONE); 199 mContainerView.setTabContainer(tabScroller); 200 } 201 mTabScrollView = tabScroller; 202 } 203 204 /** 205 * Enables or disables animation between show/hide states. 206 * If animation is disabled using this method, animations in progress 207 * will be finished. 208 * 209 * @param enabled true to animate, false to not animate. 210 */ 211 public void setShowHideAnimationEnabled(boolean enabled) { 212 mShowHideAnimationEnabled = enabled; 213 if (!enabled && mCurrentShowAnim != null) { 214 mCurrentShowAnim.end(); 215 } 216 } 217 218 public void addOnMenuVisibilityListener(OnMenuVisibilityListener listener) { 219 mMenuVisibilityListeners.add(listener); 220 } 221 222 public void removeOnMenuVisibilityListener(OnMenuVisibilityListener listener) { 223 mMenuVisibilityListeners.remove(listener); 224 } 225 226 public void dispatchMenuVisibilityChanged(boolean isVisible) { 227 if (isVisible == mLastMenuVisibility) { 228 return; 229 } 230 mLastMenuVisibility = isVisible; 231 232 final int count = mMenuVisibilityListeners.size(); 233 for (int i = 0; i < count; i++) { 234 mMenuVisibilityListeners.get(i).onMenuVisibilityChanged(isVisible); 235 } 236 } 237 238 @Override 239 public void setCustomView(int resId) { 240 setCustomView(LayoutInflater.from(mContext).inflate(resId, mActionView, false)); 241 } 242 243 @Override 244 public void setDisplayUseLogoEnabled(boolean useLogo) { 245 setDisplayOptions(useLogo ? DISPLAY_USE_LOGO : 0, DISPLAY_USE_LOGO); 246 } 247 248 @Override 249 public void setDisplayShowHomeEnabled(boolean showHome) { 250 setDisplayOptions(showHome ? DISPLAY_SHOW_HOME : 0, DISPLAY_SHOW_HOME); 251 } 252 253 @Override 254 public void setDisplayHomeAsUpEnabled(boolean showHomeAsUp) { 255 setDisplayOptions(showHomeAsUp ? DISPLAY_HOME_AS_UP : 0, DISPLAY_HOME_AS_UP); 256 } 257 258 @Override 259 public void setDisplayShowTitleEnabled(boolean showTitle) { 260 setDisplayOptions(showTitle ? DISPLAY_SHOW_TITLE : 0, DISPLAY_SHOW_TITLE); 261 } 262 263 @Override 264 public void setDisplayShowCustomEnabled(boolean showCustom) { 265 setDisplayOptions(showCustom ? DISPLAY_SHOW_CUSTOM : 0, DISPLAY_SHOW_CUSTOM); 266 } 267 268 @Override 269 public void setDisplayDisableHomeEnabled(boolean disableHome) { 270 setDisplayOptions(disableHome ? DISPLAY_DISABLE_HOME : 0, DISPLAY_DISABLE_HOME); 271 } 272 273 @Override 274 public void setTitle(int resId) { 275 setTitle(mContext.getString(resId)); 276 } 277 278 @Override 279 public void setSubtitle(int resId) { 280 setSubtitle(mContext.getString(resId)); 281 } 282 283 public void setSelectedNavigationItem(int position) { 284 switch (mActionView.getNavigationMode()) { 285 case NAVIGATION_MODE_TABS: 286 selectTab(mTabs.get(position)); 287 break; 288 case NAVIGATION_MODE_LIST: 289 mActionView.setDropdownSelectedPosition(position); 290 break; 291 default: 292 throw new IllegalStateException( 293 "setSelectedNavigationIndex not valid for current navigation mode"); 294 } 295 } 296 297 public void removeAllTabs() { 298 cleanupTabs(); 299 } 300 301 private void cleanupTabs() { 302 if (mSelectedTab != null) { 303 selectTab(null); 304 } 305 mTabs.clear(); 306 if (mTabScrollView != null) { 307 mTabScrollView.removeAllTabs(); 308 } 309 mSavedTabPosition = INVALID_POSITION; 310 } 311 312 public void setTitle(CharSequence title) { 313 mActionView.setTitle(title); 314 } 315 316 public void setSubtitle(CharSequence subtitle) { 317 mActionView.setSubtitle(subtitle); 318 } 319 320 public void setDisplayOptions(int options) { 321 mActionView.setDisplayOptions(options); 322 } 323 324 public void setDisplayOptions(int options, int mask) { 325 final int current = mActionView.getDisplayOptions(); 326 mActionView.setDisplayOptions((options & mask) | (current & ~mask)); 327 } 328 329 public void setBackgroundDrawable(Drawable d) { 330 mContainerView.setBackgroundDrawable(d); 331 } 332 333 public View getCustomView() { 334 return mActionView.getCustomNavigationView(); 335 } 336 337 public CharSequence getTitle() { 338 return mActionView.getTitle(); 339 } 340 341 public CharSequence getSubtitle() { 342 return mActionView.getSubtitle(); 343 } 344 345 public int getNavigationMode() { 346 return mActionView.getNavigationMode(); 347 } 348 349 public int getDisplayOptions() { 350 return mActionView.getDisplayOptions(); 351 } 352 353 public ActionMode startActionMode(ActionMode.Callback callback) { 354 if (mActionMode != null) { 355 mActionMode.finish(); 356 } 357 358 mContextView.killMode(); 359 ActionModeImpl mode = new ActionModeImpl(callback); 360 if (mode.dispatchOnCreate()) { 361 mWasHiddenBeforeMode = !isShowing(); 362 mode.invalidate(); 363 mContextView.initForMode(mode); 364 animateToMode(true); 365 if (mSplitView != null && mContextDisplayMode == CONTEXT_DISPLAY_SPLIT) { 366 // TODO animate this 367 mSplitView.setVisibility(View.VISIBLE); 368 } 369 mActionMode = mode; 370 return mode; 371 } 372 return null; 373 } 374 375 private void configureTab(Tab tab, int position) { 376 final TabImpl tabi = (TabImpl) tab; 377 final ActionBar.TabListener callback = tabi.getCallback(); 378 379 if (callback == null) { 380 throw new IllegalStateException("Action Bar Tab must have a Callback"); 381 } 382 383 tabi.setPosition(position); 384 mTabs.add(position, tabi); 385 386 final int count = mTabs.size(); 387 for (int i = position + 1; i < count; i++) { 388 mTabs.get(i).setPosition(i); 389 } 390 } 391 392 @Override 393 public void addTab(Tab tab) { 394 addTab(tab, mTabs.isEmpty()); 395 } 396 397 @Override 398 public void addTab(Tab tab, int position) { 399 addTab(tab, position, mTabs.isEmpty()); 400 } 401 402 @Override 403 public void addTab(Tab tab, boolean setSelected) { 404 ensureTabsExist(); 405 mTabScrollView.addTab(tab, setSelected); 406 configureTab(tab, mTabs.size()); 407 if (setSelected) { 408 selectTab(tab); 409 } 410 } 411 412 @Override 413 public void addTab(Tab tab, int position, boolean setSelected) { 414 ensureTabsExist(); 415 mTabScrollView.addTab(tab, position, setSelected); 416 configureTab(tab, position); 417 if (setSelected) { 418 selectTab(tab); 419 } 420 } 421 422 @Override 423 public Tab newTab() { 424 return new TabImpl(); 425 } 426 427 @Override 428 public void removeTab(Tab tab) { 429 removeTabAt(tab.getPosition()); 430 } 431 432 @Override 433 public void removeTabAt(int position) { 434 if (mTabScrollView == null) { 435 // No tabs around to remove 436 return; 437 } 438 439 int selectedTabPosition = mSelectedTab != null 440 ? mSelectedTab.getPosition() : mSavedTabPosition; 441 mTabScrollView.removeTabAt(position); 442 TabImpl removedTab = mTabs.remove(position); 443 if (removedTab != null) { 444 removedTab.setPosition(-1); 445 } 446 447 final int newTabCount = mTabs.size(); 448 for (int i = position; i < newTabCount; i++) { 449 mTabs.get(i).setPosition(i); 450 } 451 452 if (selectedTabPosition == position) { 453 selectTab(mTabs.isEmpty() ? null : mTabs.get(Math.max(0, position - 1))); 454 } 455 } 456 457 @Override 458 public void selectTab(Tab tab) { 459 if (getNavigationMode() != NAVIGATION_MODE_TABS) { 460 mSavedTabPosition = tab != null ? tab.getPosition() : INVALID_POSITION; 461 return; 462 } 463 464 final FragmentTransaction trans = mActivity.getFragmentManager().beginTransaction() 465 .disallowAddToBackStack(); 466 467 if (mSelectedTab == tab) { 468 if (mSelectedTab != null) { 469 mSelectedTab.getCallback().onTabReselected(mSelectedTab, trans); 470 mTabScrollView.animateToTab(tab.getPosition()); 471 } 472 } else { 473 mTabScrollView.setTabSelected(tab != null ? tab.getPosition() : Tab.INVALID_POSITION); 474 if (mSelectedTab != null) { 475 mSelectedTab.getCallback().onTabUnselected(mSelectedTab, trans); 476 } 477 mSelectedTab = (TabImpl) tab; 478 if (mSelectedTab != null) { 479 mSelectedTab.getCallback().onTabSelected(mSelectedTab, trans); 480 } 481 } 482 483 if (!trans.isEmpty()) { 484 trans.commit(); 485 } 486 } 487 488 @Override 489 public Tab getSelectedTab() { 490 return mSelectedTab; 491 } 492 493 @Override 494 public int getHeight() { 495 return mActionView.getHeight(); 496 } 497 498 @Override 499 public void show() { 500 show(true); 501 } 502 503 void show(boolean markHiddenBeforeMode) { 504 if (mCurrentShowAnim != null) { 505 mCurrentShowAnim.end(); 506 } 507 if (mContainerView.getVisibility() == View.VISIBLE) { 508 if (markHiddenBeforeMode) mWasHiddenBeforeMode = false; 509 return; 510 } 511 mContainerView.setVisibility(View.VISIBLE); 512 513 if (mShowHideAnimationEnabled) { 514 mContainerView.setAlpha(0); 515 AnimatorSet anim = new AnimatorSet(); 516 AnimatorSet.Builder b = anim.play(ObjectAnimator.ofFloat(mContainerView, "alpha", 1)); 517 if (mContentView != null) { 518 b.with(ObjectAnimator.ofFloat(mContentView, "translationY", 519 -mContainerView.getHeight(), 0)); 520 mContainerView.setTranslationY(-mContainerView.getHeight()); 521 b.with(ObjectAnimator.ofFloat(mContainerView, "translationY", 0)); 522 } 523 if (mSplitView != null && mContextDisplayMode == CONTEXT_DISPLAY_SPLIT) { 524 mSplitView.setAlpha(0); 525 b.with(ObjectAnimator.ofFloat(mSplitView, "alpha", 1)); 526 } 527 anim.addListener(mShowListener); 528 mCurrentShowAnim = anim; 529 anim.start(); 530 } else { 531 mContainerView.setAlpha(1); 532 mContainerView.setTranslationY(0); 533 mShowListener.onAnimationEnd(null); 534 } 535 } 536 537 @Override 538 public void hide() { 539 if (mCurrentShowAnim != null) { 540 mCurrentShowAnim.end(); 541 } 542 if (mContainerView.getVisibility() == View.GONE) { 543 return; 544 } 545 546 if (mShowHideAnimationEnabled) { 547 mContainerView.setAlpha(1); 548 mContainerView.setTransitioning(true); 549 AnimatorSet anim = new AnimatorSet(); 550 AnimatorSet.Builder b = anim.play(ObjectAnimator.ofFloat(mContainerView, "alpha", 0)); 551 if (mContentView != null) { 552 b.with(ObjectAnimator.ofFloat(mContentView, "translationY", 553 0, -mContainerView.getHeight())); 554 b.with(ObjectAnimator.ofFloat(mContainerView, "translationY", 555 -mContainerView.getHeight())); 556 } 557 if (mSplitView != null && mSplitView.getVisibility() == View.VISIBLE) { 558 mSplitView.setAlpha(1); 559 b.with(ObjectAnimator.ofFloat(mSplitView, "alpha", 0)); 560 } 561 anim.addListener(mHideListener); 562 mCurrentShowAnim = anim; 563 anim.start(); 564 } else { 565 mHideListener.onAnimationEnd(null); 566 } 567 } 568 569 public boolean isShowing() { 570 return mContainerView.getVisibility() == View.VISIBLE; 571 } 572 573 void animateToMode(boolean toActionMode) { 574 show(false); 575 if (mCurrentModeAnim != null) { 576 mCurrentModeAnim.end(); 577 } 578 579 mActionView.animateToVisibility(toActionMode ? View.GONE : View.VISIBLE); 580 mContextView.animateToVisibility(toActionMode ? View.VISIBLE : View.GONE); 581 if (mTabScrollView != null && !mActionView.hasEmbeddedTabs() && mActionView.isCollapsed()) { 582 mTabScrollView.animateToVisibility(toActionMode ? View.GONE : View.VISIBLE); 583 } 584 } 585 586 /** 587 * @hide 588 */ 589 public class ActionModeImpl extends ActionMode implements MenuBuilder.Callback { 590 private ActionMode.Callback mCallback; 591 private MenuBuilder mMenu; 592 private WeakReference<View> mCustomView; 593 594 public ActionModeImpl(ActionMode.Callback callback) { 595 mCallback = callback; 596 mMenu = new MenuBuilder(mActionView.getContext()) 597 .setDefaultShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM); 598 mMenu.setCallback(this); 599 } 600 601 @Override 602 public MenuInflater getMenuInflater() { 603 return new MenuInflater(mContext); 604 } 605 606 @Override 607 public Menu getMenu() { 608 return mMenu; 609 } 610 611 @Override 612 public void finish() { 613 if (mActionMode != this) { 614 // Not the active action mode - no-op 615 return; 616 } 617 618 mCallback.onDestroyActionMode(this); 619 mCallback = null; 620 animateToMode(false); 621 622 // Clear out the context mode views after the animation finishes 623 mContextView.closeMode(); 624 625 mActionMode = null; 626 627 if (mWasHiddenBeforeMode) { 628 hide(); 629 } 630 } 631 632 @Override 633 public void invalidate() { 634 mMenu.stopDispatchingItemsChanged(); 635 try { 636 mCallback.onPrepareActionMode(this, mMenu); 637 } finally { 638 mMenu.startDispatchingItemsChanged(); 639 } 640 } 641 642 public boolean dispatchOnCreate() { 643 mMenu.stopDispatchingItemsChanged(); 644 try { 645 return mCallback.onCreateActionMode(this, mMenu); 646 } finally { 647 mMenu.startDispatchingItemsChanged(); 648 } 649 } 650 651 @Override 652 public void setCustomView(View view) { 653 mContextView.setCustomView(view); 654 mCustomView = new WeakReference<View>(view); 655 } 656 657 @Override 658 public void setSubtitle(CharSequence subtitle) { 659 mContextView.setSubtitle(subtitle); 660 } 661 662 @Override 663 public void setTitle(CharSequence title) { 664 mContextView.setTitle(title); 665 } 666 667 @Override 668 public void setTitle(int resId) { 669 setTitle(mContext.getResources().getString(resId)); 670 } 671 672 @Override 673 public void setSubtitle(int resId) { 674 setSubtitle(mContext.getResources().getString(resId)); 675 } 676 677 @Override 678 public CharSequence getTitle() { 679 return mContextView.getTitle(); 680 } 681 682 @Override 683 public CharSequence getSubtitle() { 684 return mContextView.getSubtitle(); 685 } 686 687 @Override 688 public View getCustomView() { 689 return mCustomView != null ? mCustomView.get() : null; 690 } 691 692 public boolean onMenuItemSelected(MenuBuilder menu, MenuItem item) { 693 if (mCallback != null) { 694 return mCallback.onActionItemClicked(this, item); 695 } else { 696 return false; 697 } 698 } 699 700 public void onCloseMenu(MenuBuilder menu, boolean allMenusAreClosing) { 701 } 702 703 public boolean onSubMenuSelected(SubMenuBuilder subMenu) { 704 if (mCallback == null) { 705 return false; 706 } 707 708 if (!subMenu.hasVisibleItems()) { 709 return true; 710 } 711 712 new MenuPopupHelper(mContext, subMenu).show(); 713 return true; 714 } 715 716 public void onCloseSubMenu(SubMenuBuilder menu) { 717 } 718 719 public void onMenuModeChange(MenuBuilder menu) { 720 if (mCallback == null) { 721 return; 722 } 723 invalidate(); 724 mContextView.showOverflowMenu(); 725 } 726 } 727 728 /** 729 * @hide 730 */ 731 public class TabImpl extends ActionBar.Tab { 732 private ActionBar.TabListener mCallback; 733 private Object mTag; 734 private Drawable mIcon; 735 private CharSequence mText; 736 private int mPosition = -1; 737 private View mCustomView; 738 739 @Override 740 public Object getTag() { 741 return mTag; 742 } 743 744 @Override 745 public Tab setTag(Object tag) { 746 mTag = tag; 747 return this; 748 } 749 750 public ActionBar.TabListener getCallback() { 751 return mCallback; 752 } 753 754 @Override 755 public Tab setTabListener(ActionBar.TabListener callback) { 756 mCallback = callback; 757 return this; 758 } 759 760 @Override 761 public View getCustomView() { 762 return mCustomView; 763 } 764 765 @Override 766 public Tab setCustomView(View view) { 767 mCustomView = view; 768 if (mPosition >= 0) { 769 mTabScrollView.updateTab(mPosition); 770 } 771 return this; 772 } 773 774 @Override 775 public Tab setCustomView(int layoutResId) { 776 return setCustomView(LayoutInflater.from(mContext).inflate(layoutResId, null)); 777 } 778 779 @Override 780 public Drawable getIcon() { 781 return mIcon; 782 } 783 784 @Override 785 public int getPosition() { 786 return mPosition; 787 } 788 789 public void setPosition(int position) { 790 mPosition = position; 791 } 792 793 @Override 794 public CharSequence getText() { 795 return mText; 796 } 797 798 @Override 799 public Tab setIcon(Drawable icon) { 800 mIcon = icon; 801 if (mPosition >= 0) { 802 mTabScrollView.updateTab(mPosition); 803 } 804 return this; 805 } 806 807 @Override 808 public Tab setIcon(int resId) { 809 return setIcon(mContext.getResources().getDrawable(resId)); 810 } 811 812 @Override 813 public Tab setText(CharSequence text) { 814 mText = text; 815 if (mPosition >= 0) { 816 mTabScrollView.updateTab(mPosition); 817 } 818 return this; 819 } 820 821 @Override 822 public Tab setText(int resId) { 823 return setText(mContext.getResources().getText(resId)); 824 } 825 826 @Override 827 public void select() { 828 selectTab(this); 829 } 830 } 831 832 @Override 833 public void setCustomView(View view) { 834 mActionView.setCustomNavigationView(view); 835 } 836 837 @Override 838 public void setCustomView(View view, LayoutParams layoutParams) { 839 view.setLayoutParams(layoutParams); 840 mActionView.setCustomNavigationView(view); 841 } 842 843 @Override 844 public void setListNavigationCallbacks(SpinnerAdapter adapter, OnNavigationListener callback) { 845 mActionView.setDropdownAdapter(adapter); 846 mActionView.setCallback(callback); 847 } 848 849 @Override 850 public int getSelectedNavigationIndex() { 851 switch (mActionView.getNavigationMode()) { 852 case NAVIGATION_MODE_TABS: 853 return mSelectedTab != null ? mSelectedTab.getPosition() : -1; 854 case NAVIGATION_MODE_LIST: 855 return mActionView.getDropdownSelectedPosition(); 856 default: 857 return -1; 858 } 859 } 860 861 @Override 862 public int getNavigationItemCount() { 863 switch (mActionView.getNavigationMode()) { 864 case NAVIGATION_MODE_TABS: 865 return mTabs.size(); 866 case NAVIGATION_MODE_LIST: 867 SpinnerAdapter adapter = mActionView.getDropdownAdapter(); 868 return adapter != null ? adapter.getCount() : 0; 869 default: 870 return 0; 871 } 872 } 873 874 @Override 875 public int getTabCount() { 876 return mTabs.size(); 877 } 878 879 @Override 880 public void setNavigationMode(int mode) { 881 final int oldMode = mActionView.getNavigationMode(); 882 switch (oldMode) { 883 case NAVIGATION_MODE_TABS: 884 mSavedTabPosition = getSelectedNavigationIndex(); 885 selectTab(null); 886 if (!mActionView.hasEmbeddedTabs()) { 887 mTabScrollView.setVisibility(View.GONE); 888 } 889 break; 890 } 891 mActionView.setNavigationMode(mode); 892 switch (mode) { 893 case NAVIGATION_MODE_TABS: 894 ensureTabsExist(); 895 if (!mActionView.hasEmbeddedTabs()) { 896 mTabScrollView.setVisibility(View.VISIBLE); 897 } 898 if (mSavedTabPosition != INVALID_POSITION) { 899 setSelectedNavigationItem(mSavedTabPosition); 900 mSavedTabPosition = INVALID_POSITION; 901 } 902 break; 903 } 904 mActionView.setCollapsable(mode == NAVIGATION_MODE_TABS && !mHasEmbeddedTabs); 905 } 906 907 @Override 908 public Tab getTabAt(int index) { 909 return mTabs.get(index); 910 } 911 912 913 @Override 914 public void setIcon(int resId) { 915 mActionView.setIcon(resId); 916 } 917 918 @Override 919 public void setIcon(Drawable icon) { 920 mActionView.setIcon(icon); 921 } 922 923 @Override 924 public void setLogo(int resId) { 925 mActionView.setLogo(resId); 926 } 927 928 @Override 929 public void setLogo(Drawable logo) { 930 mActionView.setLogo(logo); 931 } 932} 933