ActionBarView.java revision 89edde3efad66063ff6108475976352c0c4e5fdb
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.ActionMenuView; 22import com.android.internal.view.menu.MenuBuilder; 23 24import android.app.ActionBar; 25import android.app.ActionBar.NavigationCallback; 26import android.app.Activity; 27import android.content.Context; 28import android.content.pm.ApplicationInfo; 29import android.content.pm.PackageManager; 30import android.content.res.TypedArray; 31import android.graphics.PorterDuff; 32import android.graphics.PorterDuffColorFilter; 33import android.graphics.drawable.Drawable; 34import android.text.TextUtils.TruncateAt; 35import android.util.AttributeSet; 36import android.util.DisplayMetrics; 37import android.view.ActionMode; 38import android.view.Gravity; 39import android.view.LayoutInflater; 40import android.view.Menu; 41import android.view.View; 42import android.view.ViewGroup; 43import android.widget.AdapterView; 44import android.widget.HorizontalScrollView; 45import android.widget.ImageView; 46import android.widget.LinearLayout; 47import android.widget.Spinner; 48import android.widget.SpinnerAdapter; 49import android.widget.TextView; 50 51/** 52 * @hide 53 */ 54public class ActionBarView extends ViewGroup { 55 private static final String TAG = "ActionBarView"; 56 57 /** 58 * Display options applied by default 59 */ 60 public static final int DISPLAY_DEFAULT = 0; 61 62 /** 63 * Display options that require re-layout as opposed to a simple invalidate 64 */ 65 private static final int DISPLAY_RELAYOUT_MASK = 66 ActionBar.DISPLAY_HIDE_HOME | 67 ActionBar.DISPLAY_USE_LOGO; 68 69 private final int mContentHeight; 70 71 private int mNavigationMode; 72 private int mDisplayOptions; 73 private CharSequence mTitle; 74 private CharSequence mSubtitle; 75 private Drawable mIcon; 76 private Drawable mLogo; 77 private Drawable mDivider; 78 79 private ImageView mIconView; 80 private ImageView mLogoView; 81 private LinearLayout mTitleLayout; 82 private TextView mTitleView; 83 private TextView mSubtitleView; 84 private Spinner mSpinner; 85 private HorizontalScrollView mTabScrollView; 86 private LinearLayout mTabLayout; 87 private View mCustomNavView; 88 89 private int mTitleStyleRes; 90 private int mSubtitleStyleRes; 91 92 private boolean mShowMenu; 93 private boolean mUserTitle; 94 95 private MenuBuilder mOptionsMenu; 96 private ActionMenuView mMenuView; 97 98 private ActionBarContextView mContextView; 99 100 private ActionMenuItem mLogoNavItem; 101 102 private NavigationCallback mCallback; 103 104 private final AdapterView.OnItemSelectedListener mNavItemSelectedListener = 105 new AdapterView.OnItemSelectedListener() { 106 public void onItemSelected(AdapterView parent, View view, int position, long id) { 107 if (mCallback != null) { 108 mCallback.onNavigationItemSelected(position, id); 109 } 110 } 111 public void onNothingSelected(AdapterView parent) { 112 // Do nothing 113 } 114 }; 115 116 private OnClickListener mHomeClickListener = null; 117 118 private OnClickListener mTabClickListener = null; 119 120 public ActionBarView(Context context, AttributeSet attrs) { 121 super(context, attrs); 122 123 TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.ActionBar); 124 125 final int colorFilter = a.getColor(R.styleable.ActionBar_colorFilter, 0); 126 127 if (colorFilter != 0) { 128 final Drawable d = getBackground(); 129 d.setDither(true); 130 d.setColorFilter(new PorterDuffColorFilter(colorFilter, PorterDuff.Mode.OVERLAY)); 131 } 132 133 ApplicationInfo info = context.getApplicationInfo(); 134 PackageManager pm = context.getPackageManager(); 135 mNavigationMode = a.getInt(R.styleable.ActionBar_navigationMode, 136 ActionBar.NAVIGATION_MODE_STANDARD); 137 mTitle = a.getText(R.styleable.ActionBar_title); 138 mSubtitle = a.getText(R.styleable.ActionBar_subtitle); 139 mDisplayOptions = a.getInt(R.styleable.ActionBar_displayOptions, DISPLAY_DEFAULT); 140 141 mLogo = a.getDrawable(R.styleable.ActionBar_logo); 142 if (mLogo == null) { 143 mLogo = info.loadLogo(pm); 144 } 145 mIcon = a.getDrawable(R.styleable.ActionBar_icon); 146 if (mIcon == null) { 147 mIcon = info.loadIcon(pm); 148 } 149 150 Drawable background = a.getDrawable(R.styleable.ActionBar_background); 151 if (background != null) { 152 setBackgroundDrawable(background); 153 } 154 155 mTitleStyleRes = a.getResourceId(R.styleable.ActionBar_titleTextStyle, 0); 156 mSubtitleStyleRes = a.getResourceId(R.styleable.ActionBar_subtitleTextStyle, 0); 157 158 final int customNavId = a.getResourceId(R.styleable.ActionBar_customNavigationLayout, 0); 159 if (customNavId != 0) { 160 LayoutInflater inflater = LayoutInflater.from(context); 161 mCustomNavView = (View) inflater.inflate(customNavId, null); 162 mNavigationMode = ActionBar.NAVIGATION_MODE_CUSTOM; 163 } 164 165 mContentHeight = a.getLayoutDimension(R.styleable.ActionBar_height, 0); 166 167 mDivider = a.getDrawable(R.styleable.ActionBar_divider); 168 169 a.recycle(); 170 171 if (mLogo != null || mIcon != null || mTitle != null) { 172 mLogoNavItem = new ActionMenuItem(context, 0, android.R.id.home, 0, 0, mTitle); 173 mHomeClickListener = new OnClickListener() { 174 public void onClick(View v) { 175 Context context = getContext(); 176 if (context instanceof Activity) { 177 Activity activity = (Activity) context; 178 activity.onOptionsItemSelected(mLogoNavItem); 179 } 180 } 181 }; 182 } 183 } 184 185 @Override 186 public ActionMode startActionModeForChild(View child, ActionMode.Callback callback) { 187 // No starting an action mode for an action bar child! (Where would it go?) 188 return null; 189 } 190 191 public void setCallback(NavigationCallback callback) { 192 mCallback = callback; 193 } 194 195 public void setMenu(Menu menu) { 196 MenuBuilder builder = (MenuBuilder) menu; 197 mOptionsMenu = builder; 198 if (mMenuView != null) { 199 removeView(mMenuView); 200 } 201 final ActionMenuView menuView = (ActionMenuView) builder.getMenuView( 202 MenuBuilder.TYPE_ACTION_BUTTON, null); 203 final LayoutParams layoutParams = new LayoutParams(LayoutParams.WRAP_CONTENT, 204 LayoutParams.MATCH_PARENT); 205 menuView.setLayoutParams(layoutParams); 206 addView(menuView); 207 mMenuView = menuView; 208 } 209 210 public boolean showOverflowMenu() { 211 if (mMenuView != null) { 212 return mMenuView.showOverflowMenu(); 213 } 214 return false; 215 } 216 217 public void postShowOverflowMenu() { 218 post(new Runnable() { 219 public void run() { 220 showOverflowMenu(); 221 } 222 }); 223 } 224 225 public boolean hideOverflowMenu() { 226 if (mMenuView != null) { 227 return mMenuView.hideOverflowMenu(); 228 } 229 return false; 230 } 231 232 public boolean isOverflowMenuShowing() { 233 if (mMenuView != null) { 234 return mMenuView.isOverflowMenuShowing(); 235 } 236 return false; 237 } 238 239 public boolean isOverflowReserved() { 240 return mMenuView != null && mMenuView.isOverflowReserved(); 241 } 242 243 public void setCustomNavigationView(View view) { 244 mCustomNavView = view; 245 if (view != null) { 246 setNavigationMode(ActionBar.NAVIGATION_MODE_CUSTOM); 247 } 248 } 249 250 public CharSequence getTitle() { 251 return mTitle; 252 } 253 254 /** 255 * Set the action bar title. This will always replace or override window titles. 256 * @param title Title to set 257 * 258 * @see #setWindowTitle(CharSequence) 259 */ 260 public void setTitle(CharSequence title) { 261 mUserTitle = true; 262 setTitleImpl(title); 263 } 264 265 /** 266 * Set the window title. A window title will always be replaced or overridden by a user title. 267 * @param title Title to set 268 * 269 * @see #setTitle(CharSequence) 270 */ 271 public void setWindowTitle(CharSequence title) { 272 if (!mUserTitle) { 273 setTitleImpl(title); 274 } 275 } 276 277 private void setTitleImpl(CharSequence title) { 278 mTitle = title; 279 if (mTitleView != null) { 280 mTitleView.setText(title); 281 } 282 if (mLogoNavItem != null) { 283 mLogoNavItem.setTitle(title); 284 } 285 } 286 287 public CharSequence getSubtitle() { 288 return mSubtitle; 289 } 290 291 public void setSubtitle(CharSequence subtitle) { 292 mSubtitle = subtitle; 293 if (mSubtitleView != null) { 294 mSubtitleView.setText(subtitle); 295 } 296 } 297 298 public void setDisplayOptions(int options) { 299 final int flagsChanged = options ^ mDisplayOptions; 300 mDisplayOptions = options; 301 if ((flagsChanged & DISPLAY_RELAYOUT_MASK) != 0) { 302 final int vis = (options & ActionBar.DISPLAY_HIDE_HOME) != 0 ? GONE : VISIBLE; 303 if (mLogoView != null) { 304 mLogoView.setVisibility(vis); 305 } 306 if (mIconView != null) { 307 mIconView.setVisibility(vis); 308 } 309 310 requestLayout(); 311 } else { 312 invalidate(); 313 } 314 } 315 316 public void setNavigationMode(int mode) { 317 final int oldMode = mNavigationMode; 318 if (mode != oldMode) { 319 switch (oldMode) { 320 case ActionBar.NAVIGATION_MODE_STANDARD: 321 if (mTitleLayout != null) { 322 removeView(mTitleLayout); 323 mTitleLayout = null; 324 mTitleView = null; 325 mSubtitleView = null; 326 } 327 break; 328 case ActionBar.NAVIGATION_MODE_DROPDOWN_LIST: 329 if (mSpinner != null) { 330 removeView(mSpinner); 331 mSpinner = null; 332 } 333 break; 334 case ActionBar.NAVIGATION_MODE_CUSTOM: 335 if (mCustomNavView != null) { 336 removeView(mCustomNavView); 337 mCustomNavView = null; 338 } 339 break; 340 case ActionBar.NAVIGATION_MODE_TABS: 341 if (mTabLayout != null) { 342 removeView(mTabScrollView); 343 mTabLayout = null; 344 mTabScrollView = null; 345 } 346 } 347 348 switch (mode) { 349 case ActionBar.NAVIGATION_MODE_STANDARD: 350 initTitle(); 351 break; 352 case ActionBar.NAVIGATION_MODE_DROPDOWN_LIST: 353 mSpinner = new Spinner(mContext, null, 354 com.android.internal.R.attr.actionDropDownStyle); 355 mSpinner.setOnItemSelectedListener(mNavItemSelectedListener); 356 addView(mSpinner); 357 break; 358 case ActionBar.NAVIGATION_MODE_CUSTOM: 359 addView(mCustomNavView); 360 break; 361 case ActionBar.NAVIGATION_MODE_TABS: 362 mTabScrollView = new HorizontalScrollView(getContext()); 363 mTabLayout = new LinearLayout(getContext(), null, 364 com.android.internal.R.attr.actionBarTabBarStyle); 365 mTabScrollView.addView(mTabLayout); 366 addView(mTabScrollView); 367 break; 368 } 369 mNavigationMode = mode; 370 requestLayout(); 371 } 372 } 373 374 public void setDropdownAdapter(SpinnerAdapter adapter) { 375 mSpinner.setAdapter(adapter); 376 } 377 378 public void setDropdownSelectedPosition(int position) { 379 mSpinner.setSelection(position); 380 } 381 382 public int getDropdownSelectedPosition() { 383 return mSpinner.getSelectedItemPosition(); 384 } 385 386 public View getCustomNavigationView() { 387 return mCustomNavView; 388 } 389 390 public int getNavigationMode() { 391 return mNavigationMode; 392 } 393 394 public int getDisplayOptions() { 395 return mDisplayOptions; 396 } 397 398 private TabView createTabView(ActionBar.Tab tab) { 399 final TabView tabView = new TabView(getContext(), tab); 400 tabView.setFocusable(true); 401 402 if (mTabClickListener == null) { 403 mTabClickListener = new TabClickListener(); 404 } 405 tabView.setOnClickListener(mTabClickListener); 406 return tabView; 407 } 408 409 public void addTab(ActionBar.Tab tab) { 410 final boolean isFirst = mTabLayout.getChildCount() == 0; 411 View tabView = createTabView(tab); 412 mTabLayout.addView(tabView); 413 if (isFirst) { 414 tabView.setSelected(true); 415 } 416 } 417 418 public void addTab(ActionBar.Tab tab, int position) { 419 final boolean isFirst = mTabLayout.getChildCount() == 0; 420 final TabView tabView = createTabView(tab); 421 mTabLayout.addView(tabView, position); 422 if (isFirst) { 423 tabView.setSelected(true); 424 } 425 } 426 427 public void removeTabAt(int position) { 428 mTabLayout.removeViewAt(position); 429 } 430 431 @Override 432 protected LayoutParams generateDefaultLayoutParams() { 433 // Used by custom nav views if they don't supply layout params. Everything else 434 // added to an ActionBarView should have them already. 435 return new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT); 436 } 437 438 @Override 439 protected void onFinishInflate() { 440 super.onFinishInflate(); 441 442 if ((mDisplayOptions & ActionBar.DISPLAY_HIDE_HOME) == 0) { 443 if (mLogo != null && (mDisplayOptions & ActionBar.DISPLAY_USE_LOGO) != 0) { 444 mLogoView = new ImageView(getContext(), null, 445 com.android.internal.R.attr.actionButtonStyle); 446 mLogoView.setAdjustViewBounds(true); 447 mLogoView.setLayoutParams(new LayoutParams(LayoutParams.WRAP_CONTENT, 448 LayoutParams.MATCH_PARENT)); 449 mLogoView.setImageDrawable(mLogo); 450 mLogoView.setClickable(true); 451 mLogoView.setFocusable(true); 452 mLogoView.setOnClickListener(mHomeClickListener); 453 addView(mLogoView); 454 } else if (mIcon != null) { 455 mIconView = new ImageView(getContext(), null, 456 com.android.internal.R.attr.actionButtonStyle); 457 mIconView.setAdjustViewBounds(true); 458 mIconView.setLayoutParams(new LayoutParams(LayoutParams.WRAP_CONTENT, 459 LayoutParams.MATCH_PARENT)); 460 mIconView.setImageDrawable(mIcon); 461 mIconView.setClickable(true); 462 mIconView.setFocusable(true); 463 mIconView.setOnClickListener(mHomeClickListener); 464 addView(mIconView); 465 } 466 } 467 468 switch (mNavigationMode) { 469 case ActionBar.NAVIGATION_MODE_STANDARD: 470 if (mLogoView == null) { 471 initTitle(); 472 } 473 break; 474 475 case ActionBar.NAVIGATION_MODE_DROPDOWN_LIST: 476 throw new UnsupportedOperationException( 477 "Inflating dropdown list navigation isn't supported yet!"); 478 479 case ActionBar.NAVIGATION_MODE_TABS: 480 throw new UnsupportedOperationException( 481 "Inflating tab navigation isn't supported yet!"); 482 483 case ActionBar.NAVIGATION_MODE_CUSTOM: 484 if (mCustomNavView != null) { 485 addView(mCustomNavView); 486 } 487 break; 488 } 489 } 490 491 private void initTitle() { 492 LayoutInflater inflater = LayoutInflater.from(getContext()); 493 mTitleLayout = (LinearLayout) inflater.inflate(R.layout.action_bar_title_item, null); 494 mTitleView = (TextView) mTitleLayout.findViewById(R.id.action_bar_title); 495 mSubtitleView = (TextView) mTitleLayout.findViewById(R.id.action_bar_subtitle); 496 497 if (mTitleStyleRes != 0) { 498 mTitleView.setTextAppearance(mContext, mTitleStyleRes); 499 } 500 if (mTitle != null) { 501 mTitleView.setText(mTitle); 502 } 503 504 if (mSubtitleStyleRes != 0) { 505 mSubtitleView.setTextAppearance(mContext, mSubtitleStyleRes); 506 } 507 if (mSubtitle != null) { 508 mSubtitleView.setText(mSubtitle); 509 mSubtitleView.setVisibility(VISIBLE); 510 } 511 512 addView(mTitleLayout); 513 } 514 515 public void setTabSelected(int position) { 516 final int tabCount = mTabLayout.getChildCount(); 517 for (int i = 0; i < tabCount; i++) { 518 final View child = mTabLayout.getChildAt(i); 519 child.setSelected(i == position); 520 } 521 } 522 523 public void setContextView(ActionBarContextView view) { 524 mContextView = view; 525 } 526 527 @Override 528 protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { 529 int widthMode = MeasureSpec.getMode(widthMeasureSpec); 530 if (widthMode != MeasureSpec.EXACTLY) { 531 throw new IllegalStateException(getClass().getSimpleName() + " can only be used " + 532 "with android:layout_width=\"match_parent\" (or fill_parent)"); 533 } 534 535 int heightMode = MeasureSpec.getMode(heightMeasureSpec); 536 if (heightMode != MeasureSpec.AT_MOST) { 537 throw new IllegalStateException(getClass().getSimpleName() + " can only be used " + 538 "with android:layout_height=\"wrap_content\""); 539 } 540 541 int contentWidth = MeasureSpec.getSize(widthMeasureSpec); 542 543 int maxHeight = mContentHeight > 0 ? 544 mContentHeight : MeasureSpec.getSize(heightMeasureSpec); 545 546 final int verticalPadding = getPaddingTop() + getPaddingBottom(); 547 int availableWidth = contentWidth - getPaddingLeft() - getPaddingRight(); 548 final int height = maxHeight - verticalPadding; 549 final int childSpecHeight = MeasureSpec.makeMeasureSpec(height, MeasureSpec.AT_MOST); 550 551 if (mLogoView != null && mLogoView.getVisibility() != GONE) { 552 availableWidth = measureChildView(mLogoView, availableWidth, childSpecHeight, 0); 553 } 554 if (mIconView != null && mIconView.getVisibility() != GONE) { 555 availableWidth = measureChildView(mIconView, availableWidth, childSpecHeight, 0); 556 } 557 558 if (mMenuView != null) { 559 availableWidth = measureChildView(mMenuView, availableWidth, 560 childSpecHeight, 0); 561 } 562 563 switch (mNavigationMode) { 564 case ActionBar.NAVIGATION_MODE_STANDARD: 565 if (mTitleLayout != null) { 566 measureChildView(mTitleLayout, availableWidth, childSpecHeight, 0); 567 } 568 break; 569 case ActionBar.NAVIGATION_MODE_DROPDOWN_LIST: 570 if (mSpinner != null) { 571 mSpinner.measure( 572 MeasureSpec.makeMeasureSpec(availableWidth, MeasureSpec.AT_MOST), 573 MeasureSpec.makeMeasureSpec(height, MeasureSpec.AT_MOST)); 574 } 575 break; 576 case ActionBar.NAVIGATION_MODE_CUSTOM: 577 if (mCustomNavView != null) { 578 LayoutParams lp = mCustomNavView.getLayoutParams(); 579 final int customNavWidthMode = lp.width != LayoutParams.WRAP_CONTENT ? 580 MeasureSpec.EXACTLY : MeasureSpec.AT_MOST; 581 final int customNavWidth = lp.width >= 0 ? 582 Math.min(lp.width, availableWidth) : availableWidth; 583 584 // If the action bar is wrapping to its content height, don't allow a custom 585 // view to MATCH_PARENT. 586 int customNavHeightMode; 587 if (mContentHeight <= 0) { 588 customNavHeightMode = MeasureSpec.AT_MOST; 589 } else { 590 customNavHeightMode = lp.height != LayoutParams.WRAP_CONTENT ? 591 MeasureSpec.EXACTLY : MeasureSpec.AT_MOST; 592 } 593 final int customNavHeight = lp.height >= 0 ? 594 Math.min(lp.height, height) : height; 595 mCustomNavView.measure( 596 MeasureSpec.makeMeasureSpec(customNavWidth, customNavWidthMode), 597 MeasureSpec.makeMeasureSpec(customNavHeight, customNavHeightMode)); 598 } 599 break; 600 case ActionBar.NAVIGATION_MODE_TABS: 601 if (mTabScrollView != null) { 602 mTabScrollView.measure( 603 MeasureSpec.makeMeasureSpec(availableWidth, MeasureSpec.AT_MOST), 604 MeasureSpec.makeMeasureSpec(height, MeasureSpec.EXACTLY)); 605 } 606 break; 607 } 608 609 if (mContentHeight <= 0) { 610 int measuredHeight = 0; 611 final int count = getChildCount(); 612 for (int i = 0; i < count; i++) { 613 View v = getChildAt(i); 614 int paddedViewHeight = v.getMeasuredHeight() + verticalPadding; 615 if (paddedViewHeight > measuredHeight) { 616 measuredHeight = paddedViewHeight; 617 } 618 } 619 setMeasuredDimension(contentWidth, measuredHeight); 620 } else { 621 setMeasuredDimension(contentWidth, maxHeight); 622 } 623 624 if (mContextView != null) { 625 mContextView.setHeight(getMeasuredHeight()); 626 } 627 } 628 629 private int measureChildView(View child, int availableWidth, int childSpecHeight, int spacing) { 630 child.measure(MeasureSpec.makeMeasureSpec(availableWidth, MeasureSpec.AT_MOST), 631 childSpecHeight); 632 633 availableWidth -= child.getMeasuredWidth(); 634 availableWidth -= spacing; 635 636 return availableWidth; 637 } 638 639 @Override 640 protected void onLayout(boolean changed, int l, int t, int r, int b) { 641 int x = getPaddingLeft(); 642 final int y = getPaddingTop(); 643 final int contentHeight = b - t - getPaddingTop() - getPaddingBottom(); 644 645 if (mLogoView != null && mLogoView.getVisibility() != GONE) { 646 x += positionChild(mLogoView, x, y, contentHeight); 647 } 648 if (mIconView != null && mIconView.getVisibility() != GONE) { 649 x += positionChild(mIconView, x, y, contentHeight); 650 } 651 652 switch (mNavigationMode) { 653 case ActionBar.NAVIGATION_MODE_STANDARD: 654 if (mTitleLayout != null) { 655 x += positionChild(mTitleLayout, x, y, contentHeight); 656 } 657 break; 658 case ActionBar.NAVIGATION_MODE_DROPDOWN_LIST: 659 if (mSpinner != null) { 660 x += positionChild(mSpinner, x, y, contentHeight); 661 } 662 break; 663 case ActionBar.NAVIGATION_MODE_CUSTOM: 664 if (mCustomNavView != null) { 665 x += positionChild(mCustomNavView, x, y, contentHeight); 666 } 667 break; 668 case ActionBar.NAVIGATION_MODE_TABS: 669 if (mTabScrollView != null) { 670 x += positionChild(mTabScrollView, x, y, contentHeight); 671 } 672 } 673 674 x = r - l - getPaddingRight(); 675 676 if (mMenuView != null) { 677 x -= positionChildInverse(mMenuView, x, y, contentHeight); 678 } 679 } 680 681 private int positionChild(View child, int x, int y, int contentHeight) { 682 int childWidth = child.getMeasuredWidth(); 683 int childHeight = child.getMeasuredHeight(); 684 int childTop = y + (contentHeight - childHeight) / 2; 685 686 child.layout(x, childTop, x + childWidth, childTop + childHeight); 687 688 return childWidth; 689 } 690 691 private int positionChildInverse(View child, int x, int y, int contentHeight) { 692 int childWidth = child.getMeasuredWidth(); 693 int childHeight = child.getMeasuredHeight(); 694 int childTop = y + (contentHeight - childHeight) / 2; 695 696 child.layout(x - childWidth, childTop, x, childTop + childHeight); 697 698 return childWidth; 699 } 700 701 private static class TabView extends LinearLayout { 702 private ActionBar.Tab mTab; 703 704 public TabView(Context context, ActionBar.Tab tab) { 705 super(context, null, com.android.internal.R.attr.actionBarTabStyle); 706 mTab = tab; 707 708 final View custom = tab.getCustomView(); 709 if (custom != null) { 710 addView(custom); 711 } else { 712 // TODO Style tabs based on the theme 713 714 final Drawable icon = tab.getIcon(); 715 final CharSequence text = tab.getText(); 716 717 if (icon != null) { 718 ImageView iconView = new ImageView(context); 719 iconView.setImageDrawable(icon); 720 LayoutParams lp = new LayoutParams(LayoutParams.WRAP_CONTENT, 721 LayoutParams.WRAP_CONTENT); 722 lp.gravity = Gravity.CENTER_VERTICAL; 723 iconView.setLayoutParams(lp); 724 addView(iconView); 725 } 726 727 if (text != null) { 728 TextView textView = new TextView(context, null, 729 com.android.internal.R.attr.actionBarTabTextStyle); 730 textView.setText(text); 731 textView.setSingleLine(); 732 textView.setEllipsize(TruncateAt.END); 733 LayoutParams lp = new LayoutParams(LayoutParams.WRAP_CONTENT, 734 LayoutParams.WRAP_CONTENT); 735 lp.gravity = Gravity.CENTER_VERTICAL; 736 textView.setLayoutParams(lp); 737 addView(textView); 738 } 739 } 740 741 setLayoutParams(new LayoutParams(LayoutParams.WRAP_CONTENT, 742 LayoutParams.MATCH_PARENT, 1)); 743 } 744 745 public ActionBar.Tab getTab() { 746 return mTab; 747 } 748 } 749 750 private class TabClickListener implements OnClickListener { 751 public void onClick(View view) { 752 TabView tabView = (TabView) view; 753 tabView.getTab().select(); 754 final int tabCount = mTabLayout.getChildCount(); 755 for (int i = 0; i < tabCount; i++) { 756 final View child = mTabLayout.getChildAt(i); 757 child.setSelected(child == view); 758 } 759 } 760 } 761} 762