diff options
| -rw-r--r-- | core/java/android/app/Activity.java | 4 | ||||
| -rw-r--r-- | core/java/android/widget/LinearLayout.java | 54 | ||||
| -rw-r--r-- | core/java/com/android/internal/app/ActionBarImpl.java | 103 | ||||
| -rw-r--r-- | core/java/com/android/internal/widget/ActionBarView.java | 200 | ||||
| -rw-r--r-- | core/java/com/android/internal/widget/ScrollingTabContainerView.java | 261 | ||||
| -rwxr-xr-x | core/res/res/values/attrs.xml | 3 | ||||
| -rw-r--r-- | core/res/res/values/styles.xml | 5 |
7 files changed, 428 insertions, 202 deletions
diff --git a/core/java/android/app/Activity.java b/core/java/android/app/Activity.java index 87369ab..3877bd0 100644 --- a/core/java/android/app/Activity.java +++ b/core/java/android/app/Activity.java @@ -1398,6 +1398,10 @@ public class Activity extends ContextThemeWrapper public void onConfigurationChanged(Configuration newConfig) { mCalled = true; + if (mActionBar != null) { + mActionBar.onConfigurationChanged(newConfig); + } + mFragments.dispatchConfigurationChanged(newConfig); if (mWindow != null) { diff --git a/core/java/android/widget/LinearLayout.java b/core/java/android/widget/LinearLayout.java index bac849e..6f30452 100644 --- a/core/java/android/widget/LinearLayout.java +++ b/core/java/android/widget/LinearLayout.java @@ -696,7 +696,8 @@ public class LinearLayout extends ViewGroup { mTotalLength += mDividerHeight; } - if (useLargestChild && heightMode == MeasureSpec.AT_MOST) { + if (useLargestChild && + (heightMode == MeasureSpec.AT_MOST || heightMode == MeasureSpec.UNSPECIFIED)) { mTotalLength = 0; for (int i = 0; i < count; ++i) { @@ -809,6 +810,31 @@ public class LinearLayout extends ViewGroup { } else { alternativeMaxWidth = Math.max(alternativeMaxWidth, weightedMaxWidth); + + + // We have no limit, so make all weighted views as tall as the largest child. + // Children will have already been measured once. + if (useLargestChild && widthMode == MeasureSpec.UNSPECIFIED) { + for (int i = 0; i < count; i++) { + final View child = getVirtualChildAt(i); + + if (child == null || child.getVisibility() == View.GONE) { + continue; + } + + final LinearLayout.LayoutParams lp = + (LinearLayout.LayoutParams) child.getLayoutParams(); + + float childExtra = lp.weight; + if (childExtra > 0) { + child.measure( + MeasureSpec.makeMeasureSpec(child.getMeasuredWidth(), + MeasureSpec.EXACTLY), + MeasureSpec.makeMeasureSpec(largestChildHeight, + MeasureSpec.EXACTLY)); + } + } + } } if (!allFillParent && widthMode != MeasureSpec.EXACTLY) { @@ -1044,7 +1070,8 @@ public class LinearLayout extends ViewGroup { maxHeight = Math.max(maxHeight, ascent + descent); } - if (useLargestChild && widthMode == MeasureSpec.AT_MOST) { + if (useLargestChild && + (widthMode == MeasureSpec.AT_MOST || widthMode == MeasureSpec.UNSPECIFIED)) { mTotalLength = 0; for (int i = 0; i < count; ++i) { @@ -1200,6 +1227,29 @@ public class LinearLayout extends ViewGroup { } } else { alternativeMaxHeight = Math.max(alternativeMaxHeight, weightedMaxHeight); + + // We have no limit, so make all weighted views as wide as the largest child. + // Children will have already been measured once. + if (useLargestChild && widthMode == MeasureSpec.UNSPECIFIED) { + for (int i = 0; i < count; i++) { + final View child = getVirtualChildAt(i); + + if (child == null || child.getVisibility() == View.GONE) { + continue; + } + + final LinearLayout.LayoutParams lp = + (LinearLayout.LayoutParams) child.getLayoutParams(); + + float childExtra = lp.weight; + if (childExtra > 0) { + child.measure( + MeasureSpec.makeMeasureSpec(largestChildWidth, MeasureSpec.EXACTLY), + MeasureSpec.makeMeasureSpec(child.getMeasuredHeight(), + MeasureSpec.EXACTLY)); + } + } + } } if (!allFillParent && heightMode != MeasureSpec.EXACTLY) { diff --git a/core/java/com/android/internal/app/ActionBarImpl.java b/core/java/com/android/internal/app/ActionBarImpl.java index 1e576ce..183cfbd 100644 --- a/core/java/com/android/internal/app/ActionBarImpl.java +++ b/core/java/com/android/internal/app/ActionBarImpl.java @@ -16,25 +16,27 @@ package com.android.internal.app; +import com.android.internal.R; import com.android.internal.view.menu.MenuBuilder; import com.android.internal.view.menu.MenuPopupHelper; import com.android.internal.view.menu.SubMenuBuilder; -import com.android.internal.widget.AbsActionBarView; import com.android.internal.widget.ActionBarContainer; import com.android.internal.widget.ActionBarContextView; import com.android.internal.widget.ActionBarView; +import com.android.internal.widget.ScrollingTabContainerView; import android.animation.Animator; import android.animation.Animator.AnimatorListener; import android.animation.AnimatorListenerAdapter; import android.animation.AnimatorSet; import android.animation.ObjectAnimator; -import android.animation.TimeInterpolator; import android.app.ActionBar; import android.app.Activity; import android.app.Dialog; import android.app.FragmentTransaction; import android.content.Context; +import android.content.res.Configuration; +import android.content.res.TypedArray; import android.graphics.drawable.Drawable; import android.os.Handler; import android.view.ActionMode; @@ -43,10 +45,7 @@ import android.view.Menu; import android.view.MenuInflater; import android.view.MenuItem; import android.view.View; -import android.view.ViewGroup; import android.view.Window; -import android.view.animation.DecelerateInterpolator; -import android.widget.HorizontalScrollView; import android.widget.SpinnerAdapter; import java.lang.ref.WeakReference; @@ -71,7 +70,7 @@ public class ActionBarImpl extends ActionBar { private ActionBarContextView mContextView; private ActionBarContainer mSplitView; private View mContentView; - private ViewGroup mExternalTabView; + private ScrollingTabContainerView mTabScrollView; private ArrayList<TabImpl> mTabs = new ArrayList<TabImpl>(); @@ -90,16 +89,17 @@ public class ActionBarImpl extends ActionBar { private static final int INVALID_POSITION = -1; private int mContextDisplayMode; + private boolean mHasEmbeddedTabs; + private int mContentHeight; final Handler mHandler = new Handler(); + Runnable mTabSelector; private Animator mCurrentShowAnim; private Animator mCurrentModeAnim; private boolean mShowHideAnimationEnabled; boolean mWasHiddenBeforeMode; - private static final TimeInterpolator sFadeOutInterpolator = new DecelerateInterpolator(); - final AnimatorListener mHideListener = new AnimatorListenerAdapter() { @Override public void onAnimationEnd(Animator animation) { @@ -150,21 +150,59 @@ public class ActionBarImpl extends ActionBar { "with a compatible window decor layout"); } + mHasEmbeddedTabs = mContext.getResources().getBoolean( + com.android.internal.R.bool.action_bar_embed_tabs); mActionView.setContextView(mContextView); mContextDisplayMode = mActionView.isSplitActionBar() ? CONTEXT_DISPLAY_SPLIT : CONTEXT_DISPLAY_NORMAL; - if (!mActionView.hasEmbeddedTabs()) { - HorizontalScrollView tabScroller = new HorizontalScrollView(mContext); - ViewGroup tabContainer = mActionView.createTabContainer(); - tabScroller.setHorizontalFadingEdgeEnabled(true); - tabScroller.addView(tabContainer); + TypedArray a = mContext.obtainStyledAttributes(null, R.styleable.ActionBar); + mContentHeight = a.getLayoutDimension(R.styleable.ActionBar_height, 0); + a.recycle(); + } + + public void onConfigurationChanged(Configuration newConfig) { + mHasEmbeddedTabs = mContext.getResources().getBoolean( + com.android.internal.R.bool.action_bar_embed_tabs); + + // Switch tab layout configuration if needed + if (!mHasEmbeddedTabs) { + mActionView.setEmbeddedTabView(null); + mContainerView.setTabContainer(mTabScrollView); + } else { + mContainerView.setTabContainer(null); + if (mTabScrollView != null) { + mTabScrollView.setVisibility(View.VISIBLE); + } + mActionView.setEmbeddedTabView(mTabScrollView); + } + + TypedArray a = mContext.obtainStyledAttributes(null, R.styleable.ActionBar); + mContentHeight = a.getLayoutDimension(R.styleable.ActionBar_height, 0); + a.recycle(); + + if (mTabScrollView != null) { + mTabScrollView.getLayoutParams().height = mContentHeight; + mTabScrollView.requestLayout(); + } + } + + private void ensureTabsExist() { + if (mTabScrollView != null) { + return; + } + + ScrollingTabContainerView tabScroller = mActionView.createTabContainer(); + + if (mHasEmbeddedTabs) { + tabScroller.setVisibility(View.VISIBLE); + mActionView.setEmbeddedTabView(tabScroller); + } else { tabScroller.setVisibility(getNavigationMode() == NAVIGATION_MODE_TABS ? View.VISIBLE : View.GONE); - mActionView.setExternalTabLayout(tabContainer); mContainerView.setTabContainer(tabScroller); - mExternalTabView = tabScroller; } + mTabScrollView = tabScroller; } /** @@ -269,7 +307,7 @@ public class ActionBarImpl extends ActionBar { selectTab(null); } mTabs.clear(); - mActionView.removeAllTabs(); + mTabScrollView.removeAllTabs(); mSavedTabPosition = INVALID_POSITION; } @@ -365,7 +403,8 @@ public class ActionBarImpl extends ActionBar { @Override public void addTab(Tab tab, boolean setSelected) { - mActionView.addTab(tab, setSelected); + ensureTabsExist(); + mTabScrollView.addTab(tab, setSelected); configureTab(tab, mTabs.size()); if (setSelected) { selectTab(tab); @@ -374,7 +413,8 @@ public class ActionBarImpl extends ActionBar { @Override public void addTab(Tab tab, int position, boolean setSelected) { - mActionView.addTab(tab, position, setSelected); + ensureTabsExist(); + mTabScrollView.addTab(tab, position, setSelected); configureTab(tab, position); if (setSelected) { selectTab(tab); @@ -393,9 +433,14 @@ public class ActionBarImpl extends ActionBar { @Override public void removeTabAt(int position) { + if (mTabScrollView == null) { + // No tabs around to remove + return; + } + int selectedTabPosition = mSelectedTab != null ? mSelectedTab.getPosition() : mSavedTabPosition; - mActionView.removeTabAt(position); + mTabScrollView.removeTabAt(position); TabImpl removedTab = mTabs.remove(position); if (removedTab != null) { removedTab.setPosition(-1); @@ -424,9 +469,10 @@ public class ActionBarImpl extends ActionBar { if (mSelectedTab == tab) { if (mSelectedTab != null) { mSelectedTab.getCallback().onTabReselected(mSelectedTab, trans); + mTabScrollView.animateToTab(tab.getPosition()); } } else { - mActionView.setTabSelected(tab != null ? tab.getPosition() : Tab.INVALID_POSITION); + mTabScrollView.setTabSelected(tab != null ? tab.getPosition() : Tab.INVALID_POSITION); if (mSelectedTab != null) { mSelectedTab.getCallback().onTabUnselected(mSelectedTab, trans); } @@ -705,7 +751,9 @@ public class ActionBarImpl extends ActionBar { @Override public Tab setCustomView(View view) { mCustomView = view; - if (mPosition >= 0) mActionView.updateTab(mPosition); + if (mPosition >= 0) { + mTabScrollView.updateTab(mPosition); + } return this; } @@ -736,7 +784,9 @@ public class ActionBarImpl extends ActionBar { @Override public Tab setIcon(Drawable icon) { mIcon = icon; - if (mPosition >= 0) mActionView.updateTab(mPosition); + if (mPosition >= 0) { + mTabScrollView.updateTab(mPosition); + } return this; } @@ -748,7 +798,9 @@ public class ActionBarImpl extends ActionBar { @Override public Tab setText(CharSequence text) { mText = text; - if (mPosition >= 0) mActionView.updateTab(mPosition); + if (mPosition >= 0) { + mTabScrollView.updateTab(mPosition); + } return this; } @@ -818,15 +870,16 @@ public class ActionBarImpl extends ActionBar { mSavedTabPosition = getSelectedNavigationIndex(); selectTab(null); if (!mActionView.hasEmbeddedTabs()) { - mExternalTabView.setVisibility(View.GONE); + mTabScrollView.setVisibility(View.GONE); } break; } mActionView.setNavigationMode(mode); switch (mode) { case NAVIGATION_MODE_TABS: + ensureTabsExist(); if (!mActionView.hasEmbeddedTabs()) { - mExternalTabView.setVisibility(View.VISIBLE); + mTabScrollView.setVisibility(View.VISIBLE); } if (mSavedTabPosition != INVALID_POSITION) { setSelectedNavigationItem(mSavedTabPosition); diff --git a/core/java/com/android/internal/widget/ActionBarView.java b/core/java/com/android/internal/widget/ActionBarView.java index f1887eb..ff04735 100644 --- a/core/java/com/android/internal/widget/ActionBarView.java +++ b/core/java/com/android/internal/widget/ActionBarView.java @@ -78,7 +78,7 @@ public class ActionBarView extends AbsActionBarView { private static final int DEFAULT_CUSTOM_GRAVITY = Gravity.LEFT | Gravity.CENTER_VERTICAL; - private final int mContentHeight; + private int mContentHeight; private int mNavigationMode; private int mDisplayOptions = ActionBar.DISPLAY_SHOW_HOME | ActionBar.DISPLAY_HOME_AS_UP; @@ -95,8 +95,7 @@ public class ActionBarView extends AbsActionBarView { private TextView mSubtitleView; private Spinner mSpinner; private LinearLayout mListNavLayout; - private HorizontalScrollView mTabScrollView; - private ViewGroup mTabLayout; + private ScrollingTabContainerView mTabScrollView; private View mCustomNavView; private ProgressBar mProgressView; private ProgressBar mIndeterminateProgressView; @@ -122,6 +121,8 @@ public class ActionBarView extends AbsActionBarView { private SpinnerAdapter mSpinnerAdapter; private OnNavigationListener mCallback; + private Runnable mTabSelector; + private final AdapterView.OnItemSelectedListener mNavItemSelectedListener = new AdapterView.OnItemSelectedListener() { public void onItemSelected(AdapterView parent, View view, int position, long id) { @@ -199,8 +200,6 @@ public class ActionBarView extends AbsActionBarView { mProgressBarPadding = a.getDimensionPixelOffset(R.styleable.ActionBar_progressBarPadding, 0); mItemPadding = a.getDimensionPixelOffset(R.styleable.ActionBar_itemPadding, 0); - mIncludeTabs = a.getBoolean(R.styleable.ActionBar_embeddedTabs, true); - setDisplayOptions(a.getInt(R.styleable.ActionBar_displayOptions, DISPLAY_DEFAULT)); final int customNavId = a.getResourceId(R.styleable.ActionBar_customNavigationLayout, 0); @@ -229,6 +228,12 @@ public class ActionBarView extends AbsActionBarView { } @Override + public void onDetachedFromWindow() { + super.onDetachedFromWindow(); + removeCallbacks(mTabSelector); + } + + @Override public boolean shouldDelayChildPressedState() { return false; } @@ -247,6 +252,11 @@ public class ActionBarView extends AbsActionBarView { addView(mIndeterminateProgressView); } + public void setContentHeight(int height) { + mContentHeight = height; + requestLayout(); + } + public void setSplitActionBar(boolean splitActionBar) { if (mSplitActionBar != splitActionBar) { if (mMenuView != null) { @@ -271,8 +281,9 @@ public class ActionBarView extends AbsActionBarView { return mIncludeTabs; } - public void setExternalTabLayout(ViewGroup tabLayout) { - mTabLayout = tabLayout; + public void setEmbeddedTabView(ScrollingTabContainerView tabs) { + mTabScrollView = tabs; + mIncludeTabs = tabs != null; } public void setCallback(OnNavigationListener callback) { @@ -489,7 +500,7 @@ public class ActionBarView extends AbsActionBarView { } break; case ActionBar.NAVIGATION_MODE_TABS: - if (mTabScrollView != null) { + if (mTabScrollView != null && mIncludeTabs) { removeView(mTabScrollView); } } @@ -513,8 +524,7 @@ public class ActionBarView extends AbsActionBarView { addView(mListNavLayout); break; case ActionBar.NAVIGATION_MODE_TABS: - ensureTabsExist(); - if (mTabScrollView != null) { + if (mTabScrollView != null && mIncludeTabs) { addView(mTabScrollView); } break; @@ -523,24 +533,17 @@ public class ActionBarView extends AbsActionBarView { requestLayout(); } } - - private void ensureTabsExist() { - if (!mIncludeTabs) return; - - if (mTabScrollView == null) { - mTabScrollView = new HorizontalScrollView(getContext()); - mTabScrollView.setHorizontalFadingEdgeEnabled(true); - mTabLayout = createTabContainer(); - mTabScrollView.addView(mTabLayout); - } - } - public ViewGroup createTabContainer() { - ViewGroup result = new LinearLayout(getContext(), null, + public ScrollingTabContainerView createTabContainer() { + final LinearLayout tabLayout = new LinearLayout(getContext(), null, com.android.internal.R.attr.actionBarTabBarStyle); - result.setLayoutParams(new LinearLayout.LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT, - mContentHeight)); - return result; + tabLayout.setMeasureWithLargestChildEnabled(true); + tabLayout.setLayoutParams(new LinearLayout.LayoutParams( + LinearLayout.LayoutParams.WRAP_CONTENT, mContentHeight)); + + final ScrollingTabContainerView scroller = new ScrollingTabContainerView(mContext); + scroller.setTabLayout(tabLayout); + return scroller; } public void setDropdownAdapter(SpinnerAdapter adapter) { @@ -574,51 +577,6 @@ public class ActionBarView extends AbsActionBarView { return mDisplayOptions; } - private TabView createTabView(ActionBar.Tab tab) { - final TabView tabView = new TabView(getContext(), tab); - tabView.setFocusable(true); - - if (mTabClickListener == null) { - mTabClickListener = new TabClickListener(); - } - tabView.setOnClickListener(mTabClickListener); - return tabView; - } - - public void addTab(ActionBar.Tab tab, boolean setSelected) { - ensureTabsExist(); - View tabView = createTabView(tab); - mTabLayout.addView(tabView); - if (setSelected) { - tabView.setSelected(true); - } - } - - public void addTab(ActionBar.Tab tab, int position, boolean setSelected) { - ensureTabsExist(); - final TabView tabView = createTabView(tab); - mTabLayout.addView(tabView, position); - if (setSelected) { - tabView.setSelected(true); - } - } - - public void updateTab(int position) { - ((TabView) mTabLayout.getChildAt(position)).update(); - } - - public void removeTabAt(int position) { - if (mTabLayout != null) { - mTabLayout.removeViewAt(position); - } - } - - public void removeAllTabs() { - if (mTabLayout != null) { - mTabLayout.removeAllViews(); - } - } - @Override protected LayoutParams generateDefaultLayoutParams() { // Used by custom nav views if they don't supply layout params. Everything else @@ -667,15 +625,6 @@ public class ActionBarView extends AbsActionBarView { addView(mTitleLayout); } - public void setTabSelected(int position) { - ensureTabsExist(); - final int tabCount = mTabLayout.getChildCount(); - for (int i = 0; i < tabCount; i++) { - final View child = mTabLayout.getChildAt(i); - child.setSelected(i == position); - } - } - public void setContextView(ActionBarContextView view) { mContextView = view; } @@ -948,97 +897,6 @@ public class ActionBarView extends AbsActionBarView { } } - private static class TabView extends LinearLayout { - private ActionBar.Tab mTab; - private TextView mTextView; - private ImageView mIconView; - private View mCustomView; - - public TabView(Context context, ActionBar.Tab tab) { - super(context, null, com.android.internal.R.attr.actionBarTabStyle); - mTab = tab; - - update(); - - setLayoutParams(new LayoutParams(LayoutParams.WRAP_CONTENT, - LayoutParams.MATCH_PARENT, 1)); - } - - public void update() { - final ActionBar.Tab tab = mTab; - final View custom = tab.getCustomView(); - if (custom != null) { - addView(custom); - mCustomView = custom; - if (mTextView != null) mTextView.setVisibility(GONE); - if (mIconView != null) { - mIconView.setVisibility(GONE); - mIconView.setImageDrawable(null); - } - } else { - if (mCustomView != null) { - removeView(mCustomView); - mCustomView = null; - } - - final Drawable icon = tab.getIcon(); - final CharSequence text = tab.getText(); - - if (icon != null) { - if (mIconView == null) { - ImageView iconView = new ImageView(getContext()); - LayoutParams lp = new LayoutParams(LayoutParams.WRAP_CONTENT, - LayoutParams.WRAP_CONTENT); - lp.gravity = Gravity.CENTER_VERTICAL; - iconView.setLayoutParams(lp); - addView(iconView, 0); - mIconView = iconView; - } - mIconView.setImageDrawable(icon); - mIconView.setVisibility(VISIBLE); - } else if (mIconView != null) { - mIconView.setVisibility(GONE); - mIconView.setImageDrawable(null); - } - - if (text != null) { - if (mTextView == null) { - TextView textView = new TextView(getContext(), null, - com.android.internal.R.attr.actionBarTabTextStyle); - textView.setSingleLine(); - textView.setEllipsize(TruncateAt.END); - LayoutParams lp = new LayoutParams(LayoutParams.WRAP_CONTENT, - LayoutParams.WRAP_CONTENT); - lp.gravity = Gravity.CENTER_VERTICAL; - textView.setLayoutParams(lp); - addView(textView); - mTextView = textView; - } - mTextView.setText(text); - mTextView.setVisibility(VISIBLE); - } else { - mTextView.setVisibility(GONE); - } - } - } - - public ActionBar.Tab getTab() { - return mTab; - } - } - - private class TabClickListener implements OnClickListener { - public void onClick(View view) { - TabView tabView = (TabView) view; - tabView.getTab().select(); - final int tabCount = mTabLayout.getChildCount(); - for (int i = 0; i < tabCount; i++) { - final View child = mTabLayout.getChildAt(i); - child.setSelected(child == view); - } - } - } - private static class HomeView extends FrameLayout { private View mUpView; private View mIconView; diff --git a/core/java/com/android/internal/widget/ScrollingTabContainerView.java b/core/java/com/android/internal/widget/ScrollingTabContainerView.java new file mode 100644 index 0000000..c7d37f2 --- /dev/null +++ b/core/java/com/android/internal/widget/ScrollingTabContainerView.java @@ -0,0 +1,261 @@ +/* + * Copyright (C) 2011 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.android.internal.widget; + +import android.app.ActionBar; +import android.content.Context; +import android.graphics.drawable.Drawable; +import android.text.TextUtils.TruncateAt; +import android.view.Gravity; +import android.view.View; +import android.view.ViewGroup; +import android.widget.HorizontalScrollView; +import android.widget.ImageView; +import android.widget.LinearLayout; +import android.widget.TextView; + +public class ScrollingTabContainerView extends HorizontalScrollView { + Runnable mTabSelector; + private TabClickListener mTabClickListener; + + private LinearLayout mTabLayout; + + int mMaxTabWidth; + + public ScrollingTabContainerView(Context context) { + super(context); + setHorizontalScrollBarEnabled(false); + } + + @Override + public void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { + final int widthMode = MeasureSpec.getMode(widthMeasureSpec); + setFillViewport(widthMode == MeasureSpec.EXACTLY); + + final int childCount = getChildCount(); + if (childCount > 1 && + (widthMode == MeasureSpec.EXACTLY || widthMode == MeasureSpec.AT_MOST)) { + if (childCount > 2) { + mMaxTabWidth = (int) (MeasureSpec.getSize(widthMeasureSpec) * 0.4f); + } else { + mMaxTabWidth = MeasureSpec.getSize(widthMeasureSpec) / 2; + } + } else { + mMaxTabWidth = -1; + } + + super.onMeasure(widthMeasureSpec, heightMeasureSpec); + } + + public void setTabSelected(int position) { + if (mTabLayout == null) { + return; + } + + final int tabCount = mTabLayout.getChildCount(); + for (int i = 0; i < tabCount; i++) { + final View child = mTabLayout.getChildAt(i); + final boolean isSelected = i == position; + child.setSelected(isSelected); + if (isSelected) { + animateToTab(position); + } + } + } + + public void animateToTab(int position) { + final View tabView = mTabLayout.getChildAt(position); + if (mTabSelector != null) { + removeCallbacks(mTabSelector); + } + mTabSelector = new Runnable() { + public void run() { + final int scrollPos = tabView.getLeft() - (getWidth() - tabView.getWidth()) / 2; + smoothScrollTo(scrollPos, 0); + mTabSelector = null; + } + }; + post(mTabSelector); + } + + public void setTabLayout(LinearLayout tabLayout) { + if (mTabLayout != tabLayout) { + if (mTabLayout != null) { + ((ViewGroup) mTabLayout.getParent()).removeView(mTabLayout); + } + if (tabLayout != null) { + addView(tabLayout); + } + mTabLayout = tabLayout; + } + } + + public LinearLayout getTabLayout() { + return mTabLayout; + } + + @Override + public void onDetachedFromWindow() { + super.onDetachedFromWindow(); + if (mTabSelector != null) { + removeCallbacks(mTabSelector); + } + } + + private TabView createTabView(ActionBar.Tab tab) { + final TabView tabView = new TabView(getContext(), tab); + tabView.setFocusable(true); + + if (mTabClickListener == null) { + mTabClickListener = new TabClickListener(); + } + tabView.setOnClickListener(mTabClickListener); + return tabView; + } + + public void addTab(ActionBar.Tab tab, boolean setSelected) { + View tabView = createTabView(tab); + mTabLayout.addView(tabView, new LinearLayout.LayoutParams(0, + LayoutParams.MATCH_PARENT, 1)); + if (setSelected) { + tabView.setSelected(true); + } + } + + public void addTab(ActionBar.Tab tab, int position, boolean setSelected) { + final TabView tabView = createTabView(tab); + mTabLayout.addView(tabView, position, new LinearLayout.LayoutParams( + 0, LayoutParams.MATCH_PARENT, 1)); + if (setSelected) { + tabView.setSelected(true); + } + } + + public void updateTab(int position) { + ((TabView) mTabLayout.getChildAt(position)).update(); + } + + public void removeTabAt(int position) { + if (mTabLayout != null) { + mTabLayout.removeViewAt(position); + } + } + + public void removeAllTabs() { + if (mTabLayout != null) { + mTabLayout.removeAllViews(); + } + } + + private class TabView extends LinearLayout { + private ActionBar.Tab mTab; + private TextView mTextView; + private ImageView mIconView; + private View mCustomView; + + public TabView(Context context, ActionBar.Tab tab) { + super(context, null, com.android.internal.R.attr.actionBarTabStyle); + mTab = tab; + + update(); + } + + @Override + public void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { + super.onMeasure(widthMeasureSpec, heightMeasureSpec); + + // Re-measure if we went beyond our maximum size. + if (mMaxTabWidth > 0 && getMeasuredWidth() > mMaxTabWidth) { + super.onMeasure(MeasureSpec.makeMeasureSpec(mMaxTabWidth, MeasureSpec.EXACTLY), + heightMeasureSpec); + } + } + + public void update() { + final ActionBar.Tab tab = mTab; + final View custom = tab.getCustomView(); + if (custom != null) { + addView(custom); + mCustomView = custom; + if (mTextView != null) mTextView.setVisibility(GONE); + if (mIconView != null) { + mIconView.setVisibility(GONE); + mIconView.setImageDrawable(null); + } + } else { + if (mCustomView != null) { + removeView(mCustomView); + mCustomView = null; + } + + final Drawable icon = tab.getIcon(); + final CharSequence text = tab.getText(); + + if (icon != null) { + if (mIconView == null) { + ImageView iconView = new ImageView(getContext()); + LayoutParams lp = new LayoutParams(LayoutParams.WRAP_CONTENT, + LayoutParams.WRAP_CONTENT); + lp.gravity = Gravity.CENTER_VERTICAL; + iconView.setLayoutParams(lp); + addView(iconView, 0); + mIconView = iconView; + } + mIconView.setImageDrawable(icon); + mIconView.setVisibility(VISIBLE); + } else if (mIconView != null) { + mIconView.setVisibility(GONE); + mIconView.setImageDrawable(null); + } + + if (text != null) { + if (mTextView == null) { + TextView textView = new TextView(getContext(), null, + com.android.internal.R.attr.actionBarTabTextStyle); + textView.setSingleLine(); + textView.setEllipsize(TruncateAt.END); + LayoutParams lp = new LayoutParams(LayoutParams.WRAP_CONTENT, + LayoutParams.WRAP_CONTENT); + lp.gravity = Gravity.CENTER_VERTICAL; + textView.setLayoutParams(lp); + addView(textView); + mTextView = textView; + } + mTextView.setText(text); + mTextView.setVisibility(VISIBLE); + } else { + mTextView.setVisibility(GONE); + } + } + } + + public ActionBar.Tab getTab() { + return mTab; + } + } + + private class TabClickListener implements OnClickListener { + public void onClick(View view) { + TabView tabView = (TabView) view; + tabView.getTab().select(); + final int tabCount = mTabLayout.getChildCount(); + for (int i = 0; i < tabCount; i++) { + final View child = mTabLayout.getChildAt(i); + child.setSelected(child == view); + } + } + } +} diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml index ebb70e3..c1e81c3 100755 --- a/core/res/res/values/attrs.xml +++ b/core/res/res/values/attrs.xml @@ -4913,9 +4913,6 @@ <!-- Specifies padding that should be applied to the left and right sides of system-provided items in the bar. --> <attr name="itemPadding" format="dimension" /> - <!-- Specifies whether tabs should be embedded within the bar itself (true) - or displayed elsewhere (false). --> - <attr name="embeddedTabs" format="boolean" /> </declare-styleable> <declare-styleable name="ActionMode"> diff --git a/core/res/res/values/styles.xml b/core/res/res/values/styles.xml index 26b5d95..e95094f 100644 --- a/core/res/res/values/styles.xml +++ b/core/res/res/values/styles.xml @@ -1078,7 +1078,6 @@ <item name="android:progressBarStyle">@android:style/Widget.ProgressBar.Horizontal</item> <item name="android:indeterminateProgressStyle">@android:style/Widget.ProgressBar.Small</item> <item name="android:homeLayout">@android:layout/action_bar_home</item> - <item name="android:embeddedTabs">@android:bool/action_bar_embed_tabs</item> </style> <style name="Widget.ActionMode"> @@ -1122,6 +1121,7 @@ </style> <style name="Widget.ActionBarView_TabView"> + <item name="android:gravity">center_horizontal</item> <item name="android:background">@drawable/minitab_lt</item> <item name="android:paddingLeft">4dip</item> <item name="android:paddingRight">4dip</item> @@ -1795,6 +1795,9 @@ </style> <style name="Widget.Holo.ActionBarView_TabBar" parent="Widget.ActionBarView_TabBar"> + <item name="android:divider">?android:attr/dividerVertical</item> + <item name="android:showDividers">middle</item> + <item name="android:dividerPadding">8dip</item> </style> <style name="Widget.Holo.ActionBarView_TabText" parent="Widget.ActionBarView_TabText"> |
