diff --git a/core/java/android/widget/LinearLayout.java b/core/java/android/widget/LinearLayout.java index dbe9288afa79e..7838ec093f315 100644 --- a/core/java/android/widget/LinearLayout.java +++ b/core/java/android/widget/LinearLayout.java @@ -254,6 +254,15 @@ public class LinearLayout extends ViewGroup { return mDividerPadding; } + /** + * Get the width of the current divider drawable. + * + * @hide Used internally by framework. + */ + public int getDividerWidth() { + return mDividerWidth; + } + @Override protected void onDraw(Canvas canvas) { if (mDivider == null) { diff --git a/core/java/com/android/internal/app/ActionBarImpl.java b/core/java/com/android/internal/app/ActionBarImpl.java index 57df259acca96..5c3563fc21d9d 100644 --- a/core/java/com/android/internal/app/ActionBarImpl.java +++ b/core/java/com/android/internal/app/ActionBarImpl.java @@ -19,6 +19,7 @@ package com.android.internal.app; 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; @@ -46,7 +47,6 @@ import android.view.ViewGroup; import android.view.Window; import android.view.animation.DecelerateInterpolator; import android.widget.HorizontalScrollView; -import android.widget.LinearLayout; import android.widget.SpinnerAdapter; import java.lang.ref.WeakReference; @@ -61,8 +61,6 @@ import java.util.ArrayList; */ public class ActionBarImpl extends ActionBar { private static final String TAG = "ActionBarImpl"; - private static final int NORMAL_VIEW = 0; - private static final int CONTEXT_VIEW = 1; private Context mContext; private Activity mActivity; @@ -70,8 +68,8 @@ public class ActionBarImpl extends ActionBar { private ActionBarContainer mContainerView; private ActionBarView mActionView; - private ActionBarContextView mUpperContextView; - private LinearLayout mLowerView; + private ActionBarContextView mContextView; + private ActionBarContainer mSplitView; private View mContentView; private ViewGroup mExternalTabView; @@ -102,26 +100,6 @@ public class ActionBarImpl extends ActionBar { private static final TimeInterpolator sFadeOutInterpolator = new DecelerateInterpolator(); - final AnimatorListener[] mAfterAnimation = new AnimatorListener[] { - new AnimatorListenerAdapter() { // NORMAL_VIEW - @Override - public void onAnimationEnd(Animator animation) { - if (mLowerView != null) { - mLowerView.removeAllViews(); - } - mCurrentModeAnim = null; - hideAllExcept(NORMAL_VIEW); - } - }, - new AnimatorListenerAdapter() { // CONTEXT_VIEW - @Override - public void onAnimationEnd(Animator animation) { - mCurrentModeAnim = null; - hideAllExcept(CONTEXT_VIEW); - } - } - }; - final AnimatorListener mHideListener = new AnimatorListenerAdapter() { @Override public void onAnimationEnd(Animator animation) { @@ -160,19 +138,19 @@ public class ActionBarImpl extends ActionBar { private void init(View decor) { mContext = decor.getContext(); mActionView = (ActionBarView) decor.findViewById(com.android.internal.R.id.action_bar); - mUpperContextView = (ActionBarContextView) decor.findViewById( + mContextView = (ActionBarContextView) decor.findViewById( com.android.internal.R.id.action_context_bar); - mLowerView = (LinearLayout) decor.findViewById( - com.android.internal.R.id.lower_action_context_bar); mContainerView = (ActionBarContainer) decor.findViewById( com.android.internal.R.id.action_bar_container); + mSplitView = (ActionBarContainer) decor.findViewById( + com.android.internal.R.id.split_action_bar); - if (mActionView == null || mUpperContextView == null || mContainerView == null) { + if (mActionView == null || mContextView == null || mContainerView == null) { throw new IllegalStateException(getClass().getSimpleName() + " can only be used " + "with a compatible window decor layout"); } - mActionView.setContextView(mUpperContextView); + mActionView.setContextView(mContextView); mContextDisplayMode = mActionView.isSplitActionBar() ? CONTEXT_DISPLAY_SPLIT : CONTEXT_DISPLAY_NORMAL; @@ -341,16 +319,16 @@ public class ActionBarImpl extends ActionBar { mActionMode.finish(); } - mUpperContextView.killMode(); + mContextView.killMode(); ActionMode mode = new ActionModeImpl(callback); if (callback.onCreateActionMode(mode, mode.getMenu())) { mWasHiddenBeforeMode = !isShowing(); mode.invalidate(); - mUpperContextView.initForMode(mode); - animateTo(CONTEXT_VIEW); - if (mLowerView != null) { + mContextView.initForMode(mode); + animateToMode(true); + if (mSplitView != null) { // TODO animate this - mLowerView.setVisibility(View.VISIBLE); + mSplitView.setVisibility(View.VISIBLE); } mActionMode = mode; return mode; @@ -495,6 +473,10 @@ public class ActionBarImpl extends ActionBar { mContainerView.setTranslationY(-mContainerView.getHeight()); b.with(ObjectAnimator.ofFloat(mContainerView, "translationY", 0)); } + if (mSplitView != null) { + mSplitView.setAlpha(0); + b.with(ObjectAnimator.ofFloat(mSplitView, "alpha", 1)); + } anim.addListener(mShowListener); mCurrentShowAnim = anim; anim.start(); @@ -525,6 +507,10 @@ public class ActionBarImpl extends ActionBar { b.with(ObjectAnimator.ofFloat(mContainerView, "translationY", -mContainerView.getHeight())); } + if (mSplitView != null) { + mSplitView.setAlpha(1); + b.with(ObjectAnimator.ofFloat(mSplitView, "alpha", 0)); + } anim.addListener(mHideListener); mCurrentShowAnim = anim; anim.start(); @@ -537,45 +523,14 @@ public class ActionBarImpl extends ActionBar { return mContainerView.getVisibility() == View.VISIBLE; } - long animateTo(int viewIndex) { + void animateToMode(boolean toActionMode) { show(false); if (mCurrentModeAnim != null) { mCurrentModeAnim.end(); } - AnimatorSet set = new AnimatorSet(); - - final View targetChild = mContainerView.getChildAt(viewIndex); - targetChild.setVisibility(View.VISIBLE); - targetChild.setAlpha(0); - AnimatorSet.Builder b = set.play(ObjectAnimator.ofFloat(targetChild, "alpha", 1)); - - final int count = mContainerView.getChildCount(); - for (int i = 0; i < count; i++) { - final View child = mContainerView.getChildAt(i); - if (i == viewIndex || child == mContainerView.getTabContainer()) { - continue; - } - - if (child.getVisibility() != View.GONE) { - Animator a = ObjectAnimator.ofFloat(child, "alpha", 0); - a.setInterpolator(sFadeOutInterpolator); - b.with(a); - } - } - - set.addListener(mAfterAnimation[viewIndex]); - - mCurrentModeAnim = set; - set.start(); - return set.getDuration(); - } - - private void hideAllExcept(int viewIndex) { - final int count = mContainerView.getChildCount(); - for (int i = 0; i < count; i++) { - mContainerView.getChildAt(i).setVisibility(i == viewIndex ? View.VISIBLE : View.GONE); - } + mActionView.animateToVisibility(toActionMode ? View.GONE : View.VISIBLE); + mContextView.animateToVisibility(toActionMode ? View.VISIBLE : View.GONE); } /** @@ -612,14 +567,10 @@ public class ActionBarImpl extends ActionBar { mCallback.onDestroyActionMode(this); mCallback = null; - animateTo(NORMAL_VIEW); + animateToMode(false); // Clear out the context mode views after the animation finishes - mUpperContextView.closeMode(); - if (mLowerView != null && mLowerView.getVisibility() != View.GONE) { - // TODO Animate this - mLowerView.setVisibility(View.GONE); - } + mContextView.closeMode(); mActionMode = null; if (mWasHiddenBeforeMode) { @@ -636,18 +587,18 @@ public class ActionBarImpl extends ActionBar { @Override public void setCustomView(View view) { - mUpperContextView.setCustomView(view); + mContextView.setCustomView(view); mCustomView = new WeakReference(view); } @Override public void setSubtitle(CharSequence subtitle) { - mUpperContextView.setSubtitle(subtitle); + mContextView.setSubtitle(subtitle); } @Override public void setTitle(CharSequence title) { - mUpperContextView.setTitle(title); + mContextView.setTitle(title); } @Override @@ -662,12 +613,12 @@ public class ActionBarImpl extends ActionBar { @Override public CharSequence getTitle() { - return mUpperContextView.getTitle(); + return mContextView.getTitle(); } @Override public CharSequence getSubtitle() { - return mUpperContextView.getSubtitle(); + return mContextView.getSubtitle(); } @Override @@ -707,7 +658,7 @@ public class ActionBarImpl extends ActionBar { return; } invalidate(); - mUpperContextView.showOverflowMenu(); + mContextView.showOverflowMenu(); } } diff --git a/core/java/com/android/internal/view/menu/ActionMenuPresenter.java b/core/java/com/android/internal/view/menu/ActionMenuPresenter.java index e210b78c268f4..3f089145fd310 100644 --- a/core/java/com/android/internal/view/menu/ActionMenuPresenter.java +++ b/core/java/com/android/internal/view/menu/ActionMenuPresenter.java @@ -36,11 +36,14 @@ import java.util.ArrayList; * MenuPresenter for building action menus as seen in the action bar and action modes. */ public class ActionMenuPresenter extends BaseMenuPresenter { + private static final String TAG = "ActionMenuPresenter"; + private View mOverflowButton; private boolean mReserveOverflow; private int mWidthLimit; private int mActionItemWidthLimit; private int mMaxItems; + private boolean mStrictWidthLimit; // Group IDs that have been added as actions - used temporarily, allocated here for reuse. private final SparseBooleanArray mActionButtonGroups = new SparseBooleanArray(); @@ -89,11 +92,12 @@ public class ActionMenuPresenter extends BaseMenuPresenter { mScrapActionButtonView = null; } - public void setWidthLimit(int width) { + public void setWidthLimit(int width, boolean strict) { if (mReserveOverflow) { width -= mOverflowButton.getMeasuredWidth(); } mActionItemWidthLimit = width; + mStrictWidthLimit = strict; } public void setItemLimit(int itemCount) { @@ -131,6 +135,8 @@ public class ActionMenuPresenter extends BaseMenuPresenter { if (mReserveOverflow && mMenu.getNonActionItems().size() > 0) { if (mOverflowButton == null) { mOverflowButton = new OverflowMenuButton(mContext); + mOverflowButton.setLayoutParams( + ((ActionMenuView) mMenuView).generateOverflowButtonLayoutParams()); } ViewGroup parent = (ViewGroup) mOverflowButton.getParent(); if (parent != mMenuView) { @@ -308,6 +314,8 @@ public class ActionMenuPresenter extends BaseMenuPresenter { v.measure(querySpec, querySpec); final int measuredWidth = v.getMeasuredWidth(); widthLimit -= measuredWidth; + Log.d(TAG, "flagActionItems required item " + i + " measured width " + + measuredWidth + " - " + widthLimit + " left"); if (firstActionWidth == 0) { firstActionWidth = measuredWidth; } @@ -334,13 +342,19 @@ public class ActionMenuPresenter extends BaseMenuPresenter { v.measure(querySpec, querySpec); final int measuredWidth = v.getMeasuredWidth(); widthLimit -= measuredWidth; + Log.d(TAG, "flagActionItems requested item " + i + " measured width " + + measuredWidth + " - " + widthLimit + " left"); if (firstActionWidth == 0) { firstActionWidth = measuredWidth; } - // Did this push the entire first item past halfway? - if (widthLimit + firstActionWidth <= 0) { - isAction = false; + if (mStrictWidthLimit) { + isAction = widthLimit >= 0; + Log.d(TAG, " --> strict width limit: isAction? " + isAction); + } else { + // Did this push the entire first item past the limit? + isAction = widthLimit + firstActionWidth > 0; + Log.d(TAG, " --> normal width limit: isAction? " + isAction); } } diff --git a/core/java/com/android/internal/view/menu/ActionMenuView.java b/core/java/com/android/internal/view/menu/ActionMenuView.java index 0ea9c893dcdf1..290bf08e07181 100644 --- a/core/java/com/android/internal/view/menu/ActionMenuView.java +++ b/core/java/com/android/internal/view/menu/ActionMenuView.java @@ -20,6 +20,7 @@ import android.content.res.Configuration; import android.util.AttributeSet; import android.view.Gravity; import android.view.View; +import android.view.ViewDebug; import android.view.ViewGroup; import android.widget.LinearLayout; @@ -33,6 +34,8 @@ public class ActionMenuView extends LinearLayout implements MenuBuilder.ItemInvo private boolean mReserveOverflow; private ActionMenuPresenter mPresenter; + private boolean mUpdateContentsBeforeMeasure; + private boolean mFormatItems; public ActionMenuView(Context context) { this(context, null); @@ -58,6 +61,95 @@ public class ActionMenuView extends LinearLayout implements MenuBuilder.ItemInvo } } + @Override + public void requestLayout() { + // Layout can influence how many action items fit. + mUpdateContentsBeforeMeasure = true; + super.requestLayout(); + } + + @Override + protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { + if (mUpdateContentsBeforeMeasure && mMenu != null) { + mMenu.onItemsChanged(true); + mUpdateContentsBeforeMeasure = false; + } + // If we've been given an exact size to match, apply special formatting during layout. + mFormatItems = MeasureSpec.getMode(widthMeasureSpec) == MeasureSpec.EXACTLY; + super.onMeasure(widthMeasureSpec, heightMeasureSpec); + } + + @Override + protected void onLayout(boolean changed, int left, int top, int right, int bottom) { + if (!mFormatItems) { + super.onLayout(changed, left, top, right, bottom); + return; + } + + final int childCount = getChildCount(); + final int midVertical = (top + bottom) / 2; + final int dividerWidth = getDividerWidth(); + boolean hasOverflow = false; + int overflowWidth = 0; + int nonOverflowWidth = 0; + int nonOverflowCount = 0; + int widthRemaining = right - left - getPaddingRight() - getPaddingLeft(); + for (int i = 0; i < childCount; i++) { + final View v = getChildAt(i); + if (v.getVisibility() == GONE) { + continue; + } + + LayoutParams p = (LayoutParams) v.getLayoutParams(); + if (p.isOverflowButton) { + hasOverflow = true; + overflowWidth = v.getMeasuredWidth(); + if (hasDividerBeforeChildAt(i)) { + overflowWidth += dividerWidth; + } + + int height = v.getMeasuredHeight(); + int r = getPaddingRight(); + int l = r - overflowWidth; + int t = midVertical - (height / 2); + int b = t + height; + v.layout(l, t, r, b); + + widthRemaining -= overflowWidth; + } else { + nonOverflowWidth += v.getMeasuredWidth() + p.leftMargin + p.rightMargin; + if (hasDividerBeforeChildAt(i)) { + nonOverflowWidth += dividerWidth; + } + nonOverflowCount++; + } + } + + // Try to center non-overflow items with uniformly spaced padding, including on the edges. + // Overflow will always pin to the right edge. If there isn't enough room for that, + // center in the remaining space. + if (nonOverflowWidth <= widthRemaining - overflowWidth) { + widthRemaining -= overflowWidth; + } + + final int spacing = (widthRemaining - nonOverflowWidth) / (nonOverflowCount + 1); + int startLeft = getPaddingLeft() + overflowWidth + spacing; + for (int i = 0; i < childCount; i++) { + final View v = getChildAt(i); + final LayoutParams lp = (LayoutParams) v.getLayoutParams(); + if (v.getVisibility() == GONE || lp.isOverflowButton) { + continue; + } + + startLeft += lp.leftMargin; + int width = v.getMeasuredWidth(); + int height = v.getMeasuredHeight(); + int t = midVertical - (height / 2); + v.layout(startLeft, t, startLeft + width, t + height); + startLeft += width + lp.rightMargin + spacing; + } + } + @Override public void onDetachedFromWindow() { super.onDetachedFromWindow(); @@ -97,6 +189,12 @@ public class ActionMenuView extends LinearLayout implements MenuBuilder.ItemInvo return p instanceof LayoutParams; } + public LayoutParams generateOverflowButtonLayoutParams() { + LayoutParams result = generateDefaultLayoutParams(); + result.isOverflowButton = true; + return result; + } + public boolean invokeItem(MenuItemImpl item) { return mMenu.performItemAction(item, 0); } @@ -127,4 +225,28 @@ public class ActionMenuView extends LinearLayout implements MenuBuilder.ItemInvo public boolean needsDividerBefore(); public boolean needsDividerAfter(); } + + public static class LayoutParams extends LinearLayout.LayoutParams { + @ViewDebug.ExportedProperty(category = "layout") + public boolean isOverflowButton; + + public LayoutParams(Context c, AttributeSet attrs) { + super(c, attrs); + } + + public LayoutParams(LayoutParams other) { + super((LinearLayout.LayoutParams) other); + isOverflowButton = other.isOverflowButton; + } + + public LayoutParams(int width, int height) { + super(width, height); + isOverflowButton = false; + } + + public LayoutParams(int width, int height, boolean isOverflowButton) { + super(width, height); + this.isOverflowButton = isOverflowButton; + } + } } diff --git a/core/java/com/android/internal/view/menu/MenuBuilder.java b/core/java/com/android/internal/view/menu/MenuBuilder.java index 7fba5cac2aee5..e9fcb23113c6b 100644 --- a/core/java/com/android/internal/view/menu/MenuBuilder.java +++ b/core/java/com/android/internal/view/menu/MenuBuilder.java @@ -226,6 +226,7 @@ public class MenuBuilder implements Menu { private void dispatchPresenterUpdate(boolean cleared) { if (mPresenters.isEmpty()) return; + stopDispatchingItemsChanged(); for (WeakReference ref : mPresenters) { final MenuPresenter presenter = ref.get(); if (presenter == null) { @@ -234,6 +235,7 @@ public class MenuBuilder implements Menu { presenter.updateMenuView(cleared); } } + startDispatchingItemsChanged(); } private boolean dispatchSubMenuSelected(SubMenuBuilder subMenu) { diff --git a/core/java/com/android/internal/widget/AbsActionBarView.java b/core/java/com/android/internal/widget/AbsActionBarView.java new file mode 100644 index 0000000000000..3979eabcf156d --- /dev/null +++ b/core/java/com/android/internal/widget/AbsActionBarView.java @@ -0,0 +1,211 @@ +/* + * 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 com.android.internal.view.menu.ActionMenuPresenter; +import com.android.internal.view.menu.ActionMenuView; + +import android.animation.Animator; +import android.animation.AnimatorSet; +import android.animation.ObjectAnimator; +import android.animation.TimeInterpolator; +import android.content.Context; +import android.util.AttributeSet; +import android.view.View; +import android.view.ViewGroup; +import android.view.animation.DecelerateInterpolator; + +public abstract class AbsActionBarView extends ViewGroup { + protected ActionMenuView mMenuView; + protected ActionMenuPresenter mMenuPresenter; + protected ActionBarContainer mSplitView; + + protected Animator mVisibilityAnim; + protected final VisibilityAnimListener mVisAnimListener = new VisibilityAnimListener(); + + private static final TimeInterpolator sAlphaInterpolator = new DecelerateInterpolator(); + + private static final int FADE_DURATION = 200; + + public AbsActionBarView(Context context) { + super(context); + } + + public AbsActionBarView(Context context, AttributeSet attrs) { + super(context, attrs); + } + + public AbsActionBarView(Context context, AttributeSet attrs, int defStyle) { + super(context, attrs, defStyle); + } + + public void setSplitView(ActionBarContainer splitView) { + mSplitView = splitView; + } + + public void animateToVisibility(int visibility) { + if (mVisibilityAnim != null) { + mVisibilityAnim.cancel(); + } + if (visibility == VISIBLE) { + if (getVisibility() != VISIBLE) { + setAlpha(0); + if (mSplitView != null && mMenuView != null) { + mMenuView.setAlpha(0); + } + } + ObjectAnimator anim = ObjectAnimator.ofFloat(this, "alpha", 1); + anim.setDuration(FADE_DURATION); + anim.setInterpolator(sAlphaInterpolator); + if (mSplitView != null && mMenuView != null) { + AnimatorSet set = new AnimatorSet(); + ObjectAnimator splitAnim = ObjectAnimator.ofFloat(mMenuView, "alpha", 1); + splitAnim.setDuration(FADE_DURATION); + set.addListener(mVisAnimListener.withFinalVisibility(visibility)); + set.play(anim).with(splitAnim); + } else { + anim.addListener(mVisAnimListener.withFinalVisibility(visibility)); + anim.start(); + } + } else { + ObjectAnimator anim = ObjectAnimator.ofFloat(this, "alpha", 0); + anim.setDuration(FADE_DURATION); + anim.setInterpolator(sAlphaInterpolator); + if (mSplitView != null && mMenuView != null) { + AnimatorSet set = new AnimatorSet(); + ObjectAnimator splitAnim = ObjectAnimator.ofFloat(mMenuView, "alpha", 0); + splitAnim.setDuration(FADE_DURATION); + set.addListener(mVisAnimListener.withFinalVisibility(visibility)); + set.play(anim).with(splitAnim); + } else { + anim.addListener(mVisAnimListener.withFinalVisibility(visibility)); + anim.start(); + } + } + } + + @Override + public void setVisibility(int visibility) { + if (mVisibilityAnim != null) { + mVisibilityAnim.end(); + } + super.setVisibility(visibility); + } + + public boolean showOverflowMenu() { + if (mMenuPresenter != null) { + return mMenuPresenter.showOverflowMenu(); + } + return false; + } + + public void postShowOverflowMenu() { + post(new Runnable() { + public void run() { + showOverflowMenu(); + } + }); + } + + public boolean hideOverflowMenu() { + if (mMenuPresenter != null) { + return mMenuPresenter.hideOverflowMenu(); + } + return false; + } + + public boolean isOverflowMenuShowing() { + if (mMenuPresenter != null) { + return mMenuPresenter.isOverflowMenuShowing(); + } + return false; + } + + public boolean isOverflowReserved() { + return mMenuPresenter != null && mMenuPresenter.isOverflowReserved(); + } + + public void dismissPopupMenus() { + if (mMenuPresenter != null) { + mMenuPresenter.dismissPopupMenus(); + } + } + + protected int measureChildView(View child, int availableWidth, int childSpecHeight, + int spacing) { + child.measure(MeasureSpec.makeMeasureSpec(availableWidth, MeasureSpec.AT_MOST), + childSpecHeight); + + availableWidth -= child.getMeasuredWidth(); + availableWidth -= spacing; + + return availableWidth; + } + + protected int positionChild(View child, int x, int y, int contentHeight) { + int childWidth = child.getMeasuredWidth(); + int childHeight = child.getMeasuredHeight(); + int childTop = y + (contentHeight - childHeight) / 2; + + child.layout(x, childTop, x + childWidth, childTop + childHeight); + + return childWidth; + } + + protected int positionChildInverse(View child, int x, int y, int contentHeight) { + int childWidth = child.getMeasuredWidth(); + int childHeight = child.getMeasuredHeight(); + int childTop = y + (contentHeight - childHeight) / 2; + + child.layout(x - childWidth, childTop, x, childTop + childHeight); + + return childWidth; + } + + protected class VisibilityAnimListener implements Animator.AnimatorListener { + private boolean mCanceled = false; + private int mFinalVisibility; + + public VisibilityAnimListener withFinalVisibility(int visibility) { + mFinalVisibility = visibility; + return this; + } + + @Override + public void onAnimationStart(Animator animation) { + setVisibility(VISIBLE); + mVisibilityAnim = animation; + mCanceled = false; + } + + @Override + public void onAnimationEnd(Animator animation) { + if (mCanceled) return; + + mVisibilityAnim = null; + setVisibility(mFinalVisibility); + } + + @Override + public void onAnimationCancel(Animator animation) { + mCanceled = true; + } + + @Override + public void onAnimationRepeat(Animator animation) { + } + } +} diff --git a/core/java/com/android/internal/widget/ActionBarContainer.java b/core/java/com/android/internal/widget/ActionBarContainer.java index 3deb036ea89a3..c18565df9cdd3 100644 --- a/core/java/com/android/internal/widget/ActionBarContainer.java +++ b/core/java/com/android/internal/widget/ActionBarContainer.java @@ -19,6 +19,7 @@ package com.android.internal.widget; import android.content.Context; import android.content.res.TypedArray; import android.util.AttributeSet; +import android.view.ActionMode; import android.view.MotionEvent; import android.view.View; import android.widget.FrameLayout; @@ -84,6 +85,12 @@ public class ActionBarContainer extends FrameLayout { return mTabContainer; } + @Override + public ActionMode startActionModeForChild(View child, ActionMode.Callback callback) { + // No starting an action mode for an action bar child! (Where would it go?) + return null; + } + @Override public void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { super.onMeasure(widthMeasureSpec, heightMeasureSpec); diff --git a/core/java/com/android/internal/widget/ActionBarContextView.java b/core/java/com/android/internal/widget/ActionBarContextView.java index 70fb3b2093b38..f45a3bb63a6d8 100644 --- a/core/java/com/android/internal/widget/ActionBarContextView.java +++ b/core/java/com/android/internal/widget/ActionBarContextView.java @@ -30,7 +30,7 @@ import android.util.AttributeSet; import android.view.ActionMode; import android.view.LayoutInflater; import android.view.View; -import android.view.ViewGroup; +import android.view.ViewGroup.LayoutParams; import android.view.animation.DecelerateInterpolator; import android.widget.LinearLayout; import android.widget.TextView; @@ -38,7 +38,7 @@ import android.widget.TextView; /** * @hide */ -public class ActionBarContextView extends ViewGroup implements AnimatorListener { +public class ActionBarContextView extends AbsActionBarView implements AnimatorListener { private static final String TAG = "ActionBarContextView"; private int mContentHeight; @@ -53,8 +53,6 @@ public class ActionBarContextView extends ViewGroup implements AnimatorListener private TextView mSubtitleView; private int mTitleStyleRes; private int mSubtitleStyleRes; - private ActionMenuView mMenuView; - private ActionMenuPresenter mPresenter; private Animator mCurrentAnimation; private boolean mAnimateInOnLayout; @@ -87,12 +85,6 @@ public class ActionBarContextView extends ViewGroup implements AnimatorListener com.android.internal.R.styleable.ActionMode_height, 0); a.recycle(); } - - @Override - public ActionMode startActionModeForChild(View child, ActionMode.Callback callback) { - // No starting an action mode for an existing action mode UI child! (Where would it go?) - return null; - } public void setHeight(int height) { mContentHeight = height; @@ -178,10 +170,25 @@ public class ActionBarContextView extends ViewGroup implements AnimatorListener }); final MenuBuilder menu = (MenuBuilder) mode.getMenu(); - mPresenter = new ActionMenuPresenter(); - menu.addMenuPresenter(mPresenter); - mMenuView = (ActionMenuView) mPresenter.getMenuView(this); - addView(mMenuView); + mMenuPresenter = new ActionMenuPresenter(); + menu.addMenuPresenter(mMenuPresenter); + mMenuView = (ActionMenuView) mMenuPresenter.getMenuView(this); + + final LayoutParams layoutParams = new LayoutParams(LayoutParams.WRAP_CONTENT, + LayoutParams.MATCH_PARENT); + mMenuView.setLayoutParams(layoutParams); + if (mSplitView == null) { + addView(mMenuView); + } else { + // Allow full screen width in split mode. + mMenuPresenter.setWidthLimit( + getContext().getResources().getDisplayMetrics().widthPixels, true); + // No limit to the item count; use whatever will fit. + mMenuPresenter.setItemLimit(Integer.MAX_VALUE); + // Span the whole width + layoutParams.width = LayoutParams.MATCH_PARENT; + mSplitView.addView(mMenuView); + } mAnimateInOnLayout = true; } @@ -213,28 +220,31 @@ public class ActionBarContextView extends ViewGroup implements AnimatorListener public void killMode() { finishAnimation(); removeAllViews(); + if (mSplitView != null) { + mSplitView.removeView(mMenuView); + } mCustomView = null; mMenuView = null; mAnimateInOnLayout = false; } public boolean showOverflowMenu() { - if (mPresenter != null) { - return mPresenter.showOverflowMenu(); + if (mMenuPresenter != null) { + return mMenuPresenter.showOverflowMenu(); } return false; } public boolean hideOverflowMenu() { - if (mPresenter != null) { - return mPresenter.hideOverflowMenu(); + if (mMenuPresenter != null) { + return mMenuPresenter.hideOverflowMenu(); } return false; } public boolean isOverflowMenuShowing() { - if (mPresenter != null) { - return mPresenter.isOverflowMenuShowing(); + if (mMenuPresenter != null) { + return mMenuPresenter.isOverflowMenuShowing(); } return false; } @@ -342,7 +352,7 @@ public class ActionBarContextView extends ViewGroup implements AnimatorListener private Animator makeOutAnimation() { ObjectAnimator buttonAnimator = ObjectAnimator.ofFloat(mClose, "translationX", - 0, -mClose.getWidth()); + -mClose.getWidth()); buttonAnimator.setDuration(200); buttonAnimator.addListener(this); buttonAnimator.setInterpolator(new DecelerateInterpolator()); @@ -356,7 +366,7 @@ public class ActionBarContextView extends ViewGroup implements AnimatorListener for (int i = 0; i < 0; i++) { View child = mMenuView.getChildAt(i); child.setScaleY(0); - ObjectAnimator a = ObjectAnimator.ofFloat(child, "scaleY", 1, 0); + ObjectAnimator a = ObjectAnimator.ofFloat(child, "scaleY", 0); a.setDuration(100); a.setStartDelay(i * 70); b.with(a); @@ -383,7 +393,7 @@ public class ActionBarContextView extends ViewGroup implements AnimatorListener mAnimateInOnLayout = false; } } - + if (mTitleLayout != null && mCustomView == null) { x += positionChild(mTitleLayout, x, y, contentHeight); } @@ -399,36 +409,6 @@ public class ActionBarContextView extends ViewGroup implements AnimatorListener } } - private int measureChildView(View child, int availableWidth, int childSpecHeight, int spacing) { - child.measure(MeasureSpec.makeMeasureSpec(availableWidth, MeasureSpec.AT_MOST), - childSpecHeight); - - availableWidth -= child.getMeasuredWidth(); - availableWidth -= spacing; - - return availableWidth; - } - - private int positionChild(View child, int x, int y, int contentHeight) { - int childWidth = child.getMeasuredWidth(); - int childHeight = child.getMeasuredHeight(); - int childTop = y + (contentHeight - childHeight) / 2; - - child.layout(x, childTop, x + childWidth, childTop + childHeight); - - return childWidth; - } - - private int positionChildInverse(View child, int x, int y, int contentHeight) { - int childWidth = child.getMeasuredWidth(); - int childHeight = child.getMeasuredHeight(); - int childTop = y + (contentHeight - childHeight) / 2; - - child.layout(x - childWidth, childTop, x, childTop + childHeight); - - return childWidth; - } - @Override public void onAnimationStart(Animator animation) { } diff --git a/core/java/com/android/internal/widget/ActionBarView.java b/core/java/com/android/internal/widget/ActionBarView.java index 0c13f7bfbe60e..d4813ba936be8 100644 --- a/core/java/com/android/internal/widget/ActionBarView.java +++ b/core/java/com/android/internal/widget/ActionBarView.java @@ -38,7 +38,6 @@ import android.text.TextUtils.TruncateAt; import android.util.AttributeSet; import android.util.DisplayMetrics; import android.util.Log; -import android.view.ActionMode; import android.view.Gravity; import android.view.LayoutInflater; import android.view.Menu; @@ -59,7 +58,7 @@ import android.widget.TextView; /** * @hide */ -public class ActionBarView extends ViewGroup { +public class ActionBarView extends AbsActionBarView { private static final String TAG = "ActionBarView"; /** @@ -115,11 +114,8 @@ public class ActionBarView extends ViewGroup { private boolean mIncludeTabs; private MenuBuilder mOptionsMenu; - private ActionMenuView mMenuView; - private ActionMenuPresenter mActionMenuPresenter; private ActionBarContextView mContextView; - private ViewGroup mSplitView; private ActionMenuItem mLogoNavItem; @@ -274,12 +270,6 @@ public class ActionBarView extends ViewGroup { mTabLayout = tabLayout; } - @Override - public ActionMode startActionModeForChild(View child, ActionMode.Callback callback) { - // No starting an action mode for an action bar child! (Where would it go?) - return null; - } - public void setCallback(OnNavigationListener callback) { mCallback = callback; } @@ -288,7 +278,7 @@ public class ActionBarView extends ViewGroup { if (menu == mOptionsMenu) return; if (mOptionsMenu != null) { - mOptionsMenu.removeMenuPresenter(mActionMenuPresenter); + mOptionsMenu.removeMenuPresenter(mMenuPresenter); } MenuBuilder builder = (MenuBuilder) menu; @@ -296,12 +286,12 @@ public class ActionBarView extends ViewGroup { if (mMenuView != null) { removeView(mMenuView); } - if (mActionMenuPresenter == null) { - mActionMenuPresenter = new ActionMenuPresenter(); - mActionMenuPresenter.setCallback(cb); - builder.addMenuPresenter(mActionMenuPresenter); + if (mMenuPresenter == null) { + mMenuPresenter = new ActionMenuPresenter(); + mMenuPresenter.setCallback(cb); + builder.addMenuPresenter(mMenuPresenter); } - final ActionMenuView menuView = (ActionMenuView) mActionMenuPresenter.getMenuView(this); + final ActionMenuView menuView = (ActionMenuView) mMenuPresenter.getMenuView(this); final LayoutParams layoutParams = new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.MATCH_PARENT); menuView.setLayoutParams(layoutParams); @@ -309,10 +299,12 @@ public class ActionBarView extends ViewGroup { addView(menuView); } else { // Allow full screen width in split mode. - mActionMenuPresenter.setWidthLimit( - getContext().getResources().getDisplayMetrics().widthPixels); + mMenuPresenter.setWidthLimit( + getContext().getResources().getDisplayMetrics().widthPixels, true); // No limit to the item count; use whatever will fit. - mActionMenuPresenter.setItemLimit(Integer.MAX_VALUE); + mMenuPresenter.setItemLimit(Integer.MAX_VALUE); + // Span the whole width + layoutParams.width = LayoutParams.MATCH_PARENT; if (mSplitView != null) { mSplitView.addView(menuView); } // We'll add this later if we missed it this time. @@ -320,59 +312,6 @@ public class ActionBarView extends ViewGroup { mMenuView = menuView; } - public void setSplitView(ViewGroup splitView) { - mSplitView = splitView; - splitView.setVisibility(VISIBLE); - if (mMenuView != null) { - splitView.addView(mMenuView); - } - } - - public boolean showOverflowMenu() { - if (mActionMenuPresenter != null) { - return mActionMenuPresenter.showOverflowMenu(); - } - return false; - } - - public void openOverflowMenu() { - if (mActionMenuPresenter != null) { - showOverflowMenu(); - } - } - - public void postShowOverflowMenu() { - post(new Runnable() { - public void run() { - showOverflowMenu(); - } - }); - } - - public boolean hideOverflowMenu() { - if (mActionMenuPresenter != null) { - return mActionMenuPresenter.hideOverflowMenu(); - } - return false; - } - - public boolean isOverflowMenuShowing() { - if (mActionMenuPresenter != null) { - return mActionMenuPresenter.isOverflowMenuShowing(); - } - return false; - } - - public boolean isOverflowReserved() { - return mActionMenuPresenter != null && mActionMenuPresenter.isOverflowReserved(); - } - - public void dismissPopupMenus() { - if (mActionMenuPresenter != null) { - mActionMenuPresenter.dismissPopupMenus(); - } - } - public void setCustomNavigationView(View view) { final boolean showCustom = (mDisplayOptions & ActionBar.DISPLAY_SHOW_CUSTOM) != 0; if (mCustomNavView != null && showCustom) { @@ -876,16 +815,6 @@ public class ActionBarView extends ViewGroup { } } - private int measureChildView(View child, int availableWidth, int childSpecHeight, int spacing) { - child.measure(MeasureSpec.makeMeasureSpec(availableWidth, MeasureSpec.AT_MOST), - childSpecHeight); - - availableWidth -= child.getMeasuredWidth(); - availableWidth -= spacing; - - return availableWidth; - } - @Override protected void onLayout(boolean changed, int l, int t, int r, int b) { int x = getPaddingLeft(); @@ -998,26 +927,6 @@ public class ActionBarView extends ViewGroup { } } - private int positionChild(View child, int x, int y, int contentHeight) { - int childWidth = child.getMeasuredWidth(); - int childHeight = child.getMeasuredHeight(); - int childTop = y + (contentHeight - childHeight) / 2; - - child.layout(x, childTop, x + childWidth, childTop + childHeight); - - return childWidth; - } - - private int positionChildInverse(View child, int x, int y, int contentHeight) { - int childWidth = child.getMeasuredWidth(); - int childHeight = child.getMeasuredHeight(); - int childTop = y + (contentHeight - childHeight) / 2; - - child.layout(x - childWidth, childTop, x, childTop + childHeight); - - return childWidth; - } - private static class TabView extends LinearLayout { private ActionBar.Tab mTab; diff --git a/core/res/res/layout/action_bar_title_item.xml b/core/res/res/layout/action_bar_title_item.xml index 0cf422212758e..d8b729debed23 100644 --- a/core/res/res/layout/action_bar_title_item.xml +++ b/core/res/res/layout/action_bar_title_item.xml @@ -28,5 +28,6 @@ android:layout_width="wrap_content" android:layout_height="wrap_content" android:singleLine="true" - android:ellipsize="end" /> + android:ellipsize="end" + android:visibility="gone" /> diff --git a/core/res/res/layout/screen_action_bar.xml b/core/res/res/layout/screen_action_bar.xml index 14af446abf205..9742b9476e2ed 100644 --- a/core/res/res/layout/screen_action_bar.xml +++ b/core/res/res/layout/screen_action_bar.xml @@ -43,7 +43,7 @@ This is an optimized layout for a screen with the Action Bar enabled. android:layout_weight="1" android:foregroundGravity="fill_horizontal|top" android:foreground="?android:attr/windowContentOverlay" /> - -