summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAdam Powell <adamp@google.com>2011-05-23 18:14:09 -0700
committerAdam Powell <adamp@google.com>2011-05-25 11:55:56 -0700
commitf8ac6b7394cfd37f01471bb35475ff2930eee140 (patch)
treec15928961faf0cfe7436280cb653f22e2a18c3c3
parentfeeba076c660265ac390a32ff0f0c95747714459 (diff)
downloadframeworks_base-f8ac6b7394cfd37f01471bb35475ff2930eee140.zip
frameworks_base-f8ac6b7394cfd37f01471bb35475ff2930eee140.tar.gz
frameworks_base-f8ac6b7394cfd37f01471bb35475ff2930eee140.tar.bz2
Action bar tab layout
Sync with UX on action bar tab layout behavior. Make action bar tabs behave better with configuration changes. LinearLayout now supports largest child measurement in unspecified mode. Change-Id: Id520641715a61c07e64124a0c5a70912996c98a0
-rw-r--r--core/java/android/app/Activity.java4
-rw-r--r--core/java/android/widget/LinearLayout.java54
-rw-r--r--core/java/com/android/internal/app/ActionBarImpl.java103
-rw-r--r--core/java/com/android/internal/widget/ActionBarView.java200
-rw-r--r--core/java/com/android/internal/widget/ScrollingTabContainerView.java261
-rwxr-xr-xcore/res/res/values/attrs.xml3
-rw-r--r--core/res/res/values/styles.xml5
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">