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