diff options
Diffstat (limited to 'core/java')
19 files changed, 259 insertions, 56 deletions
diff --git a/core/java/android/content/ClipboardManager.java b/core/java/android/content/ClipboardManager.java index 800d0d2..dfd1820 100644 --- a/core/java/android/content/ClipboardManager.java +++ b/core/java/android/content/ClipboardManager.java @@ -77,7 +77,20 @@ public class ClipboardManager extends android.text.ClipboardManager { } }; + /** + * Defines a listener callback that is invoked when the primary clip on the clipboard changes. + * Objects that want to register a listener call + * {@link android.content.ClipboardManager#addPrimaryClipChangedListener(OnPrimaryClipChangedListener) + * addPrimaryClipChangedListener()} with an + * object that implements OnPrimaryClipChangedListener. + * + */ public interface OnPrimaryClipChangedListener { + + /** + * Callback that is invoked by {@link android.content.ClipboardManager} when the primary + * clip changes. + */ void onPrimaryClipChanged(); } diff --git a/core/java/android/database/sqlite/SQLiteConnection.java b/core/java/android/database/sqlite/SQLiteConnection.java index 04f6377..acdc488 100644 --- a/core/java/android/database/sqlite/SQLiteConnection.java +++ b/core/java/android/database/sqlite/SQLiteConnection.java @@ -390,6 +390,8 @@ public final class SQLiteConnection implements CancellationSignal.OnCancelListen // Called by SQLiteConnectionPool only. void reconfigure(SQLiteDatabaseConfiguration configuration) { + mOnlyAllowReadOnlyOperations = false; + // Register custom functions. final int functionCount = configuration.customFunctions.size(); for (int i = 0; i < functionCount; i++) { diff --git a/core/java/android/net/DhcpInfoInternal.java b/core/java/android/net/DhcpInfoInternal.java index fa77bc5..7ab8047 100644 --- a/core/java/android/net/DhcpInfoInternal.java +++ b/core/java/android/net/DhcpInfoInternal.java @@ -19,9 +19,8 @@ package android.net; import android.text.TextUtils; import android.util.Log; -import java.net.InetAddress; import java.net.Inet4Address; -import java.net.UnknownHostException; +import java.net.InetAddress; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; @@ -42,6 +41,11 @@ public class DhcpInfoInternal { public String serverAddress; public int leaseDuration; + /** + * Vendor specific information (from RFC 2132). + */ + public String vendorInfo; + private Collection<RouteInfo> mRoutes; public DhcpInfoInternal() { diff --git a/core/java/android/net/nsd/INsdManager.aidl b/core/java/android/net/nsd/INsdManager.aidl index 077a675..3361a7b 100644 --- a/core/java/android/net/nsd/INsdManager.aidl +++ b/core/java/android/net/nsd/INsdManager.aidl @@ -26,4 +26,5 @@ import android.os.Messenger; interface INsdManager { Messenger getMessenger(); + void setEnabled(boolean enable); } diff --git a/core/java/android/net/nsd/NsdManager.java b/core/java/android/net/nsd/NsdManager.java index dac8d20..77e97e1 100644 --- a/core/java/android/net/nsd/NsdManager.java +++ b/core/java/android/net/nsd/NsdManager.java @@ -16,6 +16,8 @@ package android.net.nsd; +import android.annotation.SdkConstant; +import android.annotation.SdkConstant.SdkConstantType; import android.content.Context; import android.os.Binder; import android.os.IBinder; @@ -133,6 +135,40 @@ public class NsdManager { private static final String TAG = "NsdManager"; INsdManager mService; + /** + * Broadcast intent action to indicate whether network service discovery is + * enabled or disabled. An extra {@link #EXTRA_NSD_STATE} provides the state + * information as int. + * + * @see #EXTRA_NSD_STATE + */ + @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) + public static final String ACTION_NSD_STATE_CHANGED = + "android.net.nsd.STATE_CHANGED"; + + /** + * The lookup key for an int that indicates whether network service discovery is enabled + * or disabled. Retrieve it with {@link android.content.Intent#getIntExtra(String,int)}. + * + * @see #NSD_STATE_DISABLED + * @see #NSD_STATE_ENABLED + */ + public static final String EXTRA_NSD_STATE = "nsd_state"; + + /** + * Network service discovery is disabled + * + * @see #ACTION_NSD_STATE_CHANGED + */ + public static final int NSD_STATE_DISABLED = 1; + + /** + * Network service discovery is enabled + * + * @see #ACTION_NSD_STATE_CHANGED + */ + public static final int NSD_STATE_ENABLED = 2; + private static final int BASE = Protocol.BASE_NSD_MANAGER; /** @hide */ @@ -188,6 +224,12 @@ public class NsdManager { /** @hide */ public static final int STOP_RESOLVE_SUCCEEDED = BASE + 23; + /** @hide */ + public static final int ENABLE = BASE + 24; + /** @hide */ + public static final int DISABLE = BASE + 25; + + /** * Create a new Nsd instance. Applications use * {@link android.content.Context#getSystemService Context.getSystemService()} to retrieve @@ -312,8 +354,8 @@ public class NsdManager { private DnsSdResolveListener mDnsSdResolveListener; private ActionListener mDnsSdStopResolveListener; - AsyncChannel mAsyncChannel; - ServiceHandler mHandler; + private AsyncChannel mAsyncChannel; + private ServiceHandler mHandler; class ServiceHandler extends Handler { ServiceHandler(Looper looper) { super(looper); @@ -594,6 +636,13 @@ public class NsdManager { c.mAsyncChannel.sendMessage(STOP_RESOLVE); } + /** Internal use only @hide */ + public void setEnabled(boolean enabled) { + try { + mService.setEnabled(enabled); + } catch (RemoteException e) { } + } + /** * Get a reference to NetworkService handler. This is used to establish * an AsyncChannel communication with the service diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java index 6dfbb2f..3a5fdd1 100644 --- a/core/java/android/provider/Settings.java +++ b/core/java/android/provider/Settings.java @@ -3277,6 +3277,12 @@ public final class Settings { "wifi_mobile_data_transition_wakelock_timeout_ms"; /** + * Whether network service discovery is enabled. + * @hide + */ + public static final String NSD_ON = "nsd_on"; + + /** * Whether background data usage is allowed by the user. See * ConnectivityManager for more info. */ diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java index bd054bc..537c474 100644 --- a/core/java/android/view/View.java +++ b/core/java/android/view/View.java @@ -2472,6 +2472,12 @@ public class View implements Drawable.Callback, Drawable.Callback2, KeyEvent.Cal int mSystemUiVisibility; /** + * Reference count for transient state. + * @see #setHasTransientState(boolean) + */ + int mTransientStateCount = 0; + + /** * Count of how many windows this view has been attached to. */ int mWindowAttachCount; @@ -5400,21 +5406,32 @@ public class View implements Drawable.Callback, Drawable.Callback2, KeyEvent.Cal /** * Set whether this view is currently tracking transient state that the - * framework should attempt to preserve when possible. + * framework should attempt to preserve when possible. This flag is reference counted, + * so every call to setHasTransientState(true) should be paired with a later call + * to setHasTransientState(false). * * @param hasTransientState true if this view has transient state */ public void setHasTransientState(boolean hasTransientState) { - if (hasTransientState() == hasTransientState) return; - - mPrivateFlags2 = (mPrivateFlags2 & ~HAS_TRANSIENT_STATE) | - (hasTransientState ? HAS_TRANSIENT_STATE : 0); - if (mParent != null) { - try { - mParent.childHasTransientStateChanged(this, hasTransientState); - } catch (AbstractMethodError e) { - Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() + - " does not fully implement ViewParent", e); + mTransientStateCount = hasTransientState ? mTransientStateCount + 1 : + mTransientStateCount - 1; + if (mTransientStateCount < 0) { + mTransientStateCount = 0; + Log.e(VIEW_LOG_TAG, "hasTransientState decremented below 0: " + + "unmatched pair of setHasTransientState calls"); + } + if ((hasTransientState && mTransientStateCount == 1) || + (hasTransientState && mTransientStateCount == 0)) { + // update flag if we've just incremented up from 0 or decremented down to 0 + mPrivateFlags2 = (mPrivateFlags2 & ~HAS_TRANSIENT_STATE) | + (hasTransientState ? HAS_TRANSIENT_STATE : 0); + if (mParent != null) { + try { + mParent.childHasTransientStateChanged(this, hasTransientState); + } catch (AbstractMethodError e) { + Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() + + " does not fully implement ViewParent", e); + } } } } @@ -12297,7 +12314,7 @@ public class View implements Drawable.Callback, Drawable.Callback2, KeyEvent.Cal final int flags = parent.mGroupFlags; final boolean initialized = a.isInitialized(); if (!initialized) { - a.initialize(mRight - mLeft, mBottom - mTop, getWidth(), getHeight()); + a.initialize(mRight - mLeft, mBottom - mTop, parent.getWidth(), parent.getHeight()); a.initializeInvalidateRegion(0, 0, mRight - mLeft, mBottom - mTop); onAnimationStart(); } diff --git a/core/java/android/view/ViewPropertyAnimator.java b/core/java/android/view/ViewPropertyAnimator.java index 3626aba..e573056 100644 --- a/core/java/android/view/ViewPropertyAnimator.java +++ b/core/java/android/view/ViewPropertyAnimator.java @@ -714,6 +714,7 @@ public class ViewPropertyAnimator { * value accordingly. */ private void startAnimation() { + mView.setHasTransientState(true); ValueAnimator animator = ValueAnimator.ofFloat(1.0f); ArrayList<NameValuesHolder> nameValueList = (ArrayList<NameValuesHolder>) mPendingAnimations.clone(); @@ -960,6 +961,7 @@ public class ViewPropertyAnimator { @Override public void onAnimationEnd(Animator animation) { + mView.setHasTransientState(false); if (mListener != null) { mListener.onAnimationEnd(animation); } diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java index 3d40b2f..247f673 100644 --- a/core/java/android/view/ViewRootImpl.java +++ b/core/java/android/view/ViewRootImpl.java @@ -1199,13 +1199,13 @@ public final class ViewRootImpl implements ViewParent, } } + // Execute enqueued actions on every traversal in case a detached view enqueued an action + getRunQueue().executeActions(attachInfo.mHandler); + boolean insetsChanged = false; boolean layoutRequested = mLayoutRequested && !mStopped; if (layoutRequested) { - // Execute enqueued actions on every layout in case a view that was detached - // enqueued an action after being detached - getRunQueue().executeActions(attachInfo.mHandler); final Resources res = mView.getContext().getResources(); diff --git a/core/java/android/webkit/WebViewClassic.java b/core/java/android/webkit/WebViewClassic.java index 9c5e852..c8cfb0a 100644 --- a/core/java/android/webkit/WebViewClassic.java +++ b/core/java/android/webkit/WebViewClassic.java @@ -1485,8 +1485,7 @@ public final class WebViewClassic implements WebViewProvider, WebViewProvider.Sc switch (eventType) { case WebViewInputDispatcher.EVENT_TYPE_LONG_PRESS: HitTestResult hitTest = getHitTestResult(); - if (hitTest != null - && hitTest.getType() != HitTestResult.UNKNOWN_TYPE) { + if (hitTest != null) { performLongClick(); } break; diff --git a/core/java/android/webkit/WebViewCore.java b/core/java/android/webkit/WebViewCore.java index aea23c0..f86262e 100644 --- a/core/java/android/webkit/WebViewCore.java +++ b/core/java/android/webkit/WebViewCore.java @@ -46,6 +46,8 @@ import junit.framework.Assert; import java.util.ArrayList; import java.util.Collection; +import java.util.Iterator; +import java.util.LinkedList; import java.util.Map; import java.util.Set; @@ -1182,7 +1184,7 @@ public final class WebViewCore { private Handler mHandler; // Message queue for containing messages before the WebCore thread is // ready. - private ArrayList<Message> mMessages = new ArrayList<Message>(); + private LinkedList<Message> mMessages = new LinkedList<Message>(); // Flag for blocking messages. This is used during DESTROY to avoid // posting more messages to the EventHub or to WebView's event handler. private boolean mBlockMessages; @@ -1822,10 +1824,13 @@ public final class WebViewCore { mDrawIsScheduled = false; } if (mMessages != null) { - Throwable throwable = new Throwable( - "EventHub.removeMessages(int what = " + what + ") is not supported " + - "before the WebViewCore is set up."); - Log.w(LOGTAG, Log.getStackTraceString(throwable)); + Iterator<Message> iter = mMessages.iterator(); + while (iter.hasNext()) { + Message m = iter.next(); + if (m.what == what) { + iter.remove(); + } + } } else { mHandler.removeMessages(what); } diff --git a/core/java/android/widget/AbsSeekBar.java b/core/java/android/widget/AbsSeekBar.java index ca5648a..ae68794 100644 --- a/core/java/android/widget/AbsSeekBar.java +++ b/core/java/android/widget/AbsSeekBar.java @@ -123,7 +123,7 @@ public abstract class AbsSeekBar extends ProgressBar { invalidate(); if (needUpdate) { updateThumbPos(getWidth(), getHeight()); - if (thumb.isStateful()) { + if (thumb != null && thumb.isStateful()) { // Note that if the states are different this won't work. // For now, let's consider that an app bug. int[] state = getDrawableState(); diff --git a/core/java/android/widget/Switch.java b/core/java/android/widget/Switch.java index 0786909..471f259 100644 --- a/core/java/android/widget/Switch.java +++ b/core/java/android/widget/Switch.java @@ -29,6 +29,8 @@ import android.text.Layout; import android.text.StaticLayout; import android.text.TextPaint; import android.text.TextUtils; +import android.text.method.AllCapsTransformationMethod; +import android.text.method.TransformationMethod2; import android.util.AttributeSet; import android.view.Gravity; import android.view.MotionEvent; @@ -91,6 +93,7 @@ public class Switch extends CompoundButton { private ColorStateList mTextColors; private Layout mOnLayout; private Layout mOffLayout; + private TransformationMethod2 mSwitchTransformationMethod; @SuppressWarnings("hiding") private final Rect mTempRect = new Rect(); @@ -207,6 +210,15 @@ public class Switch extends CompoundButton { setSwitchTypefaceByIndex(typefaceIndex, styleIndex); + boolean allCaps = appearance.getBoolean(com.android.internal.R.styleable. + TextAppearance_textAllCaps, false); + if (allCaps) { + mSwitchTransformationMethod = new AllCapsTransformationMethod(getContext()); + mSwitchTransformationMethod.setLengthChangesAllowed(true); + } else { + mSwitchTransformationMethod = null; + } + appearance.recycle(); } @@ -526,8 +538,12 @@ public class Switch extends CompoundButton { } private Layout makeLayout(CharSequence text) { - return new StaticLayout(text, mTextPaint, - (int) Math.ceil(Layout.getDesiredWidth(text, mTextPaint)), + final CharSequence transformed = (mSwitchTransformationMethod != null) + ? mSwitchTransformationMethod.getTransformation(text, this) + : text; + + return new StaticLayout(transformed, mTextPaint, + (int) Math.ceil(Layout.getDesiredWidth(transformed, mTextPaint)), Layout.Alignment.ALIGN_NORMAL, 1.f, 0, true); } diff --git a/core/java/com/android/internal/app/ActionBarImpl.java b/core/java/com/android/internal/app/ActionBarImpl.java index 1ba6d43..d0071e3 100644 --- a/core/java/com/android/internal/app/ActionBarImpl.java +++ b/core/java/com/android/internal/app/ActionBarImpl.java @@ -16,6 +16,7 @@ package com.android.internal.app; +import com.android.internal.view.ActionBarPolicy; import com.android.internal.view.menu.MenuBuilder; import com.android.internal.view.menu.MenuPopupHelper; import com.android.internal.view.menu.SubMenuBuilder; @@ -183,18 +184,13 @@ public class ActionBarImpl extends ActionBar { mContextDisplayMode = mActionView.isSplitActionBar() ? CONTEXT_DISPLAY_SPLIT : CONTEXT_DISPLAY_NORMAL; - // Older apps get the home button interaction enabled by default. - // Newer apps need to enable it explicitly. - setHomeButtonEnabled(mContext.getApplicationInfo().targetSdkVersion < - Build.VERSION_CODES.ICE_CREAM_SANDWICH); - - setHasEmbeddedTabs(mContext.getResources().getBoolean( - com.android.internal.R.bool.action_bar_embed_tabs)); + ActionBarPolicy abp = ActionBarPolicy.get(mContext); + setHomeButtonEnabled(abp.enableHomeButtonByDefault()); + setHasEmbeddedTabs(abp.hasEmbeddedTabs()); } public void onConfigurationChanged(Configuration newConfig) { - setHasEmbeddedTabs(mContext.getResources().getBoolean( - com.android.internal.R.bool.action_bar_embed_tabs)); + setHasEmbeddedTabs(ActionBarPolicy.get(mContext).hasEmbeddedTabs()); } private void setHasEmbeddedTabs(boolean hasEmbeddedTabs) { diff --git a/core/java/com/android/internal/util/AsyncChannel.java b/core/java/com/android/internal/util/AsyncChannel.java index 0c5d5ef..d1c2d2e 100644 --- a/core/java/com/android/internal/util/AsyncChannel.java +++ b/core/java/com/android/internal/util/AsyncChannel.java @@ -150,7 +150,7 @@ public class AsyncChannel { */ public static final int CMD_CHANNEL_DISCONNECTED = BASE + 4; - private static final int CMD_TO_STRING_COUNT = CMD_CHANNEL_DISCONNECTED + 1; + private static final int CMD_TO_STRING_COUNT = CMD_CHANNEL_DISCONNECTED - BASE + 1; private static String[] sCmdToString = new String[CMD_TO_STRING_COUNT]; static { sCmdToString[CMD_CHANNEL_HALF_CONNECTED - BASE] = "CMD_CHANNEL_HALF_CONNECTED"; diff --git a/core/java/com/android/internal/view/ActionBarPolicy.java b/core/java/com/android/internal/view/ActionBarPolicy.java new file mode 100644 index 0000000..0c6b780 --- /dev/null +++ b/core/java/com/android/internal/view/ActionBarPolicy.java @@ -0,0 +1,90 @@ +/* + * Copyright (C) 2012 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.view; + +import com.android.internal.R; + +import android.content.Context; +import android.content.res.Resources; +import android.content.res.TypedArray; +import android.os.Build; +import android.view.ViewConfiguration; + +/** + * Allows components to query for various configuration policy decisions + * about how the action bar should lay out and behave on the current device. + */ +public class ActionBarPolicy { + private Context mContext; + + public static ActionBarPolicy get(Context context) { + return new ActionBarPolicy(context); + } + + private ActionBarPolicy(Context context) { + mContext = context; + } + + public int getMaxActionButtons() { + return mContext.getResources().getInteger(R.integer.max_action_buttons); + } + + public boolean showsOverflowMenuButton() { + return !ViewConfiguration.get(mContext).hasPermanentMenuKey(); + } + + public int getEmbeddedMenuWidthLimit() { + return mContext.getResources().getDisplayMetrics().widthPixels / 2; + } + + public boolean hasEmbeddedTabs() { + final int targetSdk = mContext.getApplicationInfo().targetSdkVersion; + if (targetSdk >= Build.VERSION_CODES.JELLY_BEAN) { + return mContext.getResources().getBoolean(R.bool.action_bar_embed_tabs); + } + + // The embedded tabs policy changed in Jellybean; give older apps the old policy + // so they get what they expect. + return mContext.getResources().getBoolean(R.bool.action_bar_embed_tabs_pre_jb); + } + + public int getTabContainerHeight() { + TypedArray a = mContext.obtainStyledAttributes(null, R.styleable.ActionBar, + com.android.internal.R.attr.actionBarStyle, 0); + int height = a.getLayoutDimension(R.styleable.ActionBar_height, 0); + Resources r = mContext.getResources(); + if (!hasEmbeddedTabs()) { + // Stacked tabs; limit the height + height = Math.min(height, + r.getDimensionPixelSize(R.dimen.action_bar_stacked_max_height)); + } + a.recycle(); + return height; + } + + public boolean enableHomeButtonByDefault() { + // Older apps get the home button interaction enabled by default. + // Newer apps need to enable it explicitly. + return mContext.getApplicationInfo().targetSdkVersion < + Build.VERSION_CODES.ICE_CREAM_SANDWICH; + } + + public int getStackedTabMaxWidth() { + return mContext.getResources().getDimensionPixelSize( + R.dimen.action_bar_stacked_tab_max_width); + } +} diff --git a/core/java/com/android/internal/view/menu/ActionMenuPresenter.java b/core/java/com/android/internal/view/menu/ActionMenuPresenter.java index dca45a9..73324c0 100644 --- a/core/java/com/android/internal/view/menu/ActionMenuPresenter.java +++ b/core/java/com/android/internal/view/menu/ActionMenuPresenter.java @@ -16,6 +16,7 @@ package com.android.internal.view.menu; +import com.android.internal.view.ActionBarPolicy; import com.android.internal.view.menu.ActionMenuView.ActionMenuChildView; import android.content.Context; @@ -29,7 +30,6 @@ import android.view.MenuItem; import android.view.SoundEffectConstants; import android.view.View; import android.view.View.MeasureSpec; -import android.view.ViewConfiguration; import android.view.ViewGroup; import android.widget.ImageButton; @@ -79,17 +79,18 @@ public class ActionMenuPresenter extends BaseMenuPresenter final Resources res = context.getResources(); + final ActionBarPolicy abp = ActionBarPolicy.get(context); if (!mReserveOverflowSet) { - mReserveOverflow = !ViewConfiguration.get(context).hasPermanentMenuKey(); + mReserveOverflow = abp.showsOverflowMenuButton(); } if (!mWidthLimitSet) { - mWidthLimit = res.getDisplayMetrics().widthPixels / 2; + mWidthLimit = abp.getEmbeddedMenuWidthLimit(); } // Measure for initial configuration if (!mMaxItemsSet) { - mMaxItems = res.getInteger(com.android.internal.R.integer.max_action_buttons); + mMaxItems = abp.getMaxActionButtons(); } int width = mWidthLimit; diff --git a/core/java/com/android/internal/widget/AbsActionBarView.java b/core/java/com/android/internal/widget/AbsActionBarView.java index 06f5158..25a9c54 100644 --- a/core/java/com/android/internal/widget/AbsActionBarView.java +++ b/core/java/com/android/internal/widget/AbsActionBarView.java @@ -161,10 +161,12 @@ public abstract class AbsActionBarView extends ViewGroup { @Override public void setVisibility(int visibility) { - if (mVisibilityAnim != null) { - mVisibilityAnim.end(); + if (visibility != getVisibility()) { + if (mVisibilityAnim != null) { + mVisibilityAnim.end(); + } + super.setVisibility(visibility); } - super.setVisibility(visibility); } public boolean showOverflowMenu() { diff --git a/core/java/com/android/internal/widget/ScrollingTabContainerView.java b/core/java/com/android/internal/widget/ScrollingTabContainerView.java index 1767d68..83ac896 100644 --- a/core/java/com/android/internal/widget/ScrollingTabContainerView.java +++ b/core/java/com/android/internal/widget/ScrollingTabContainerView.java @@ -15,7 +15,7 @@ */ package com.android.internal.widget; -import com.android.internal.R; +import com.android.internal.view.ActionBarPolicy; import android.animation.Animator; import android.animation.ObjectAnimator; @@ -23,7 +23,6 @@ import android.animation.TimeInterpolator; import android.app.ActionBar; import android.content.Context; import android.content.res.Configuration; -import android.content.res.TypedArray; import android.graphics.drawable.Drawable; import android.text.TextUtils.TruncateAt; import android.view.Gravity; @@ -55,6 +54,7 @@ public class ScrollingTabContainerView extends HorizontalScrollView private boolean mAllowCollapse; int mMaxTabWidth; + int mStackedTabMaxWidth; private int mContentHeight; private int mSelectedTabIndex; @@ -69,10 +69,9 @@ public class ScrollingTabContainerView extends HorizontalScrollView super(context); setHorizontalScrollBarEnabled(false); - TypedArray a = getContext().obtainStyledAttributes(null, R.styleable.ActionBar, - com.android.internal.R.attr.actionBarStyle, 0); - setContentHeight(a.getLayoutDimension(R.styleable.ActionBar_height, 0)); - a.recycle(); + ActionBarPolicy abp = ActionBarPolicy.get(context); + setContentHeight(abp.getTabContainerHeight()); + mStackedTabMaxWidth = abp.getStackedTabMaxWidth(); mTabLayout = createTabLayout(); addView(mTabLayout, new ViewGroup.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, @@ -93,6 +92,7 @@ public class ScrollingTabContainerView extends HorizontalScrollView } else { mMaxTabWidth = MeasureSpec.getSize(widthMeasureSpec) / 2; } + mMaxTabWidth = Math.min(mMaxTabWidth, mStackedTabMaxWidth); } else { mMaxTabWidth = -1; } @@ -187,6 +187,7 @@ public class ScrollingTabContainerView extends HorizontalScrollView final LinearLayout tabLayout = new LinearLayout(getContext(), null, com.android.internal.R.attr.actionBarTabBarStyle); tabLayout.setMeasureWithLargestChildEnabled(true); + tabLayout.setGravity(Gravity.CENTER); tabLayout.setLayoutParams(new LinearLayout.LayoutParams( LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.MATCH_PARENT)); return tabLayout; @@ -205,12 +206,11 @@ public class ScrollingTabContainerView extends HorizontalScrollView protected void onConfigurationChanged(Configuration newConfig) { super.onConfigurationChanged(newConfig); + ActionBarPolicy abp = ActionBarPolicy.get(getContext()); // Action bar can change size on configuration changes. // Reread the desired height from the theme-specified style. - TypedArray a = getContext().obtainStyledAttributes(null, R.styleable.ActionBar, - com.android.internal.R.attr.actionBarStyle, 0); - setContentHeight(a.getLayoutDimension(R.styleable.ActionBar_height, 0)); - a.recycle(); + setContentHeight(abp.getTabContainerHeight()); + mStackedTabMaxWidth = abp.getStackedTabMaxWidth(); } public void animateToVisibility(int visibility) { |
