diff options
Diffstat (limited to 'core')
| -rw-r--r-- | core/java/android/transition/ChangeText.java (renamed from core/java/android/transition/TextChange.java) | 54 | ||||
| -rw-r--r-- | core/java/android/transition/Fade.java | 45 | ||||
| -rw-r--r-- | core/java/android/transition/Scene.java | 19 | ||||
| -rw-r--r-- | core/java/android/transition/Transition.java | 12 | ||||
| -rw-r--r-- | core/java/android/transition/TransitionManager.java | 5 | ||||
| -rw-r--r-- | core/java/android/transition/TransitionSet.java | 9 | ||||
| -rw-r--r-- | core/java/android/transition/Visibility.java | 65 | ||||
| -rw-r--r-- | core/java/android/widget/ListPopupWindow.java | 15 | ||||
| -rw-r--r-- | core/java/android/widget/PopupMenu.java | 14 | ||||
| -rw-r--r-- | core/java/android/widget/PopupWindow.java | 73 | ||||
| -rw-r--r-- | core/java/com/android/internal/transition/ActionBarTransition.java | 6 | ||||
| -rw-r--r-- | core/java/com/android/internal/view/menu/ActionMenuPresenter.java | 2 | ||||
| -rw-r--r-- | core/java/com/android/internal/view/menu/MenuPopupHelper.java | 8 | ||||
| -rw-r--r-- | core/java/com/android/internal/widget/ActionBarView.java | 6 | 
14 files changed, 221 insertions, 112 deletions
diff --git a/core/java/android/transition/TextChange.java b/core/java/android/transition/ChangeText.java index cf190a1..b1be70f 100644 --- a/core/java/android/transition/TextChange.java +++ b/core/java/android/transition/ChangeText.java @@ -37,7 +37,7 @@ import java.util.Map;   *   * @hide   */ -public class TextChange extends Transition { +public class ChangeText extends Transition {      private static final String LOG_TAG = "TextChange"; @@ -103,7 +103,7 @@ public class TextChange extends Transition {       * transition is run.       * @return this textChange object.       */ -    public TextChange setChangeBehavior(int changeBehavior) { +    public ChangeText setChangeBehavior(int changeBehavior) {          if (changeBehavior >= CHANGE_BEHAVIOR_KEEP && changeBehavior <= CHANGE_BEHAVIOR_OUT_IN) {              mChangeBehavior = changeBehavior;          } @@ -179,9 +179,13 @@ public class TextChange extends Transition {              startSelectionStart = startSelectionEnd = endSelectionStart = endSelectionEnd = -1;          }          if (!startText.equals(endText)) { -            view.setText(startText); -            if (view instanceof EditText) { -                setSelection(((EditText) view), startSelectionStart, startSelectionEnd); +            final int startColor = (Integer) startVals.get(PROPNAME_TEXT_COLOR); +            final int endColor = (Integer) endVals.get(PROPNAME_TEXT_COLOR); +            if (mChangeBehavior != CHANGE_BEHAVIOR_IN) { +                view.setText(startText); +                if (view instanceof EditText) { +                    setSelection(((EditText) view), startSelectionStart, startSelectionEnd); +                }              }              Animator anim;              if (mChangeBehavior == CHANGE_BEHAVIOR_KEEP) { @@ -200,8 +204,6 @@ public class TextChange extends Transition {                  });              } else {                  // Fade out start text -                final int startColor = (Integer) startVals.get(PROPNAME_TEXT_COLOR); -                final int endColor = (Integer) endVals.get(PROPNAME_TEXT_COLOR);                  ValueAnimator outAnim = null, inAnim = null;                  if (mChangeBehavior == CHANGE_BEHAVIOR_OUT_IN ||                          mChangeBehavior == CHANGE_BEHAVIOR_OUT) { @@ -210,8 +212,8 @@ public class TextChange extends Transition {                          @Override                          public void onAnimationUpdate(ValueAnimator animation) {                              int currAlpha = (Integer) animation.getAnimatedValue(); -                            view.setTextColor(currAlpha << 24 | Color.red(startColor) << 16 | -                                    Color.green(startColor) << 8 | Color.red(startColor)); +                            view.setTextColor(currAlpha << 24 | startColor & 0xff0000 | +                                    startColor & 0xff00 | startColor & 0xff);                          }                      });                      outAnim.addListener(new AnimatorListenerAdapter() { @@ -225,6 +227,8 @@ public class TextChange extends Transition {                                              endSelectionEnd);                                  }                              } +                            // restore opaque alpha and correct end color +                            view.setTextColor(endColor);                          }                      });                  } @@ -239,6 +243,13 @@ public class TextChange extends Transition {                                      Color.green(endColor) << 8 | Color.red(endColor));                          }                      }); +                    inAnim.addListener(new AnimatorListenerAdapter() { +                        @Override +                        public void onAnimationCancel(Animator animation) { +                            // restore opaque alpha and correct end color +                            view.setTextColor(endColor); +                        } +                    });                  }                  if (outAnim != null && inAnim != null) {                      anim = new AnimatorSet(); @@ -251,21 +262,32 @@ public class TextChange extends Transition {                  }              }              TransitionListener transitionListener = new TransitionListenerAdapter() { -                boolean mCanceled = false; +                int mPausedColor = 0;                  @Override                  public void onTransitionPause(Transition transition) { -                    view.setText(endText); -                    if (view instanceof EditText) { -                        setSelection(((EditText) view), endSelectionStart, endSelectionEnd); +                    if (mChangeBehavior != CHANGE_BEHAVIOR_IN) { +                        view.setText(endText); +                        if (view instanceof EditText) { +                            setSelection(((EditText) view), endSelectionStart, endSelectionEnd); +                        } +                    } +                    if (mChangeBehavior > CHANGE_BEHAVIOR_KEEP) { +                        mPausedColor = view.getCurrentTextColor(); +                        view.setTextColor(endColor);                      }                  }                  @Override                  public void onTransitionResume(Transition transition) { -                    view.setText(startText); -                    if (view instanceof EditText) { -                        setSelection(((EditText) view), startSelectionStart, startSelectionEnd); +                    if (mChangeBehavior != CHANGE_BEHAVIOR_IN) { +                        view.setText(startText); +                        if (view instanceof EditText) { +                            setSelection(((EditText) view), startSelectionStart, startSelectionEnd); +                        } +                    } +                    if (mChangeBehavior > CHANGE_BEHAVIOR_KEEP) { +                        view.setTextColor(mPausedColor);                      }                  }              }; diff --git a/core/java/android/transition/Fade.java b/core/java/android/transition/Fade.java index 5f948bd..8edb1ff 100644 --- a/core/java/android/transition/Fade.java +++ b/core/java/android/transition/Fade.java @@ -30,6 +30,24 @@ import android.view.ViewGroup;   * {@link View#setVisibility(int)} state of the view as well as whether it   * is parented in the current view hierarchy.   * + * <p>The ability of this transition to fade out a particular view, and the + * way that that fading operation takes place, is based on + * the situation of the view in the view hierarchy. For example, if a view was + * simply removed from its parent, then the view will be added into a {@link + * android.view.ViewGroupOverlay} while fading. If a visible view is + * changed to be {@link View#GONE} or {@link View#INVISIBLE}, then the + * visibility will be changed to {@link View#VISIBLE} for the duration of + * the animation. However, if a view is in a hierarchy which is also altering + * its visibility, the situation can be more complicated. In general, if a + * view that is no longer in the hierarchy in the end scene still has a + * parent (so its parent hierarchy was removed, but it was not removed from + * its parent), then it will be left alone to avoid side-effects from + * improperly removing it from its parent. The only exception to this is if + * the previous {@link Scene} was + * {@link Scene#getSceneForLayout(android.view.ViewGroup, int, android.content.Context) + * created from a layout resource file}, then it is considered safe to un-parent + * the starting scene view in order to fade it out.</p> + *   * <p>A Fade transition can be described in a resource file by using the   * tag <code>fade</code>, along with the standard   * attributes of {@link android.R.styleable#Fade} and @@ -167,7 +185,7 @@ public class Fade extends Visibility {          if ((mFadingMode & OUT) != OUT) {              return null;          } -        View view; +        View view = null;          View startView = (startValues != null) ? startValues.view : null;          View endView = (endValues != null) ? endValues.view : null;          if (DBG) { @@ -177,9 +195,28 @@ public class Fade extends Visibility {          View overlayView = null;          View viewToKeep = null;          if (endView == null || endView.getParent() == null) { -            // view was removed: add the start view to the Overlay -            view = startView; -            overlayView = view; +            if (endView != null) { +                // endView was removed from its parent - add it to the overlay +                view = overlayView = endView; +            } else if (startView != null) { +                // endView does not exist. Use startView only under certain +                // conditions, because placing a view in an overlay necessitates +                // it being removed from its current parent +                if (startView.getParent() == null) { +                    // no parent - safe to use +                    view = overlayView = startView; +                } else if (startView.getParent() instanceof View && +                        startView.getParent().getParent() == null) { +                    View startParent = (View) startView.getParent(); +                    int id = startParent.getId(); +                    if (id != View.NO_ID && sceneRoot.findViewById(id) != null && mCanRemoveViews) { +                        // no parent, but its parent is unparented  but the parent +                        // hierarchy has been replaced by a new hierarchy with the same id +                        // and it is safe to un-parent startView +                        view = overlayView = startView; +                    } +                } +            }          } else {              // visibility change              if (endVisibility == View.INVISIBLE) { diff --git a/core/java/android/transition/Scene.java b/core/java/android/transition/Scene.java index f81eeef..d798abe 100644 --- a/core/java/android/transition/Scene.java +++ b/core/java/android/transition/Scene.java @@ -157,11 +157,11 @@ public final class Scene {      public void enter() {          // Apply layout change, if any -        if (mLayoutId >= 0 || mLayout != null) { +        if (mLayoutId > 0 || mLayout != null) {              // empty out parent container before adding to it              getSceneRoot().removeAllViews(); -            if (mLayoutId >= 0) { +            if (mLayoutId > 0) {                  LayoutInflater.from(mContext).inflate(mLayoutId, mSceneRoot);              } else {                  mSceneRoot.addView(mLayout); @@ -242,4 +242,19 @@ public final class Scene {          mExitAction = action;      } + +    /** +     * Returns whether this Scene was created by a layout resource file, determined +     * by the layoutId passed into +     * {@link #getSceneForLayout(android.view.ViewGroup, int, android.content.Context)}. +     * This is called by TransitionManager to determine whether it is safe for views from +     * this scene to be removed from their parents when the scene is exited, which is +     * used by {@link Fade} to fade these views out (the views must be removed from +     * their parent in order to add them to the overlay for fading purposes). If a +     * Scene is not based on a resource file, then the impact of removing views +     * arbitrarily is unknown and should be avoided. +     */ +    boolean isCreatedFromLayoutResource() { +        return (mLayoutId > 0); +    }  }
\ No newline at end of file diff --git a/core/java/android/transition/Transition.java b/core/java/android/transition/Transition.java index a552fd4..dcf668b 100644 --- a/core/java/android/transition/Transition.java +++ b/core/java/android/transition/Transition.java @@ -118,6 +118,14 @@ public abstract class Transition implements Cloneable {      // Scene Root is set at createAnimator() time in the cloned Transition      ViewGroup mSceneRoot = null; +    // Whether removing views from their parent is possible. This is only for views +    // in the start scene, which are no longer in the view hierarchy. This property +    // is determined by whether the previous Scene was created from a layout +    // resource, and thus the views from the exited scene are going away anyway +    // and can be removed as necessary to achieve a particular effect, such as +    // removing them from parents to add them to overlays. +    boolean mCanRemoveViews = false; +      // Track all animators in use in case the transition gets canceled and needs to      // cancel running animators      private ArrayList<Animator> mCurrentAnimators = new ArrayList<Animator>(); @@ -1445,6 +1453,10 @@ public abstract class Transition implements Cloneable {          return this;      } +    void setCanRemoveViews(boolean canRemoveViews) { +        mCanRemoveViews = canRemoveViews; +    } +      @Override      public String toString() {          return toString(""); diff --git a/core/java/android/transition/TransitionManager.java b/core/java/android/transition/TransitionManager.java index 44ca4e5..9be91d0 100644 --- a/core/java/android/transition/TransitionManager.java +++ b/core/java/android/transition/TransitionManager.java @@ -178,6 +178,11 @@ public class TransitionManager {          Transition transitionClone = transition.clone();          transitionClone.setSceneRoot(sceneRoot); +        Scene oldScene = Scene.getCurrentScene(sceneRoot); +        if (oldScene != null && oldScene.isCreatedFromLayoutResource()) { +            transitionClone.setCanRemoveViews(true); +        } +          sceneChangeSetup(sceneRoot, transitionClone);          scene.enter(); diff --git a/core/java/android/transition/TransitionSet.java b/core/java/android/transition/TransitionSet.java index 6fdd309..79cd8b6 100644 --- a/core/java/android/transition/TransitionSet.java +++ b/core/java/android/transition/TransitionSet.java @@ -340,6 +340,15 @@ public class TransitionSet extends Transition {      }      @Override +    void setCanRemoveViews(boolean canRemoveViews) { +        super.setCanRemoveViews(canRemoveViews); +        int numTransitions = mTransitions.size(); +        for (int i = 0; i < numTransitions; ++i) { +            mTransitions.get(i).setCanRemoveViews(canRemoveViews); +        } +    } + +    @Override      String toString(String indent) {          String result = super.toString(indent);          for (int i = 0; i < mTransitions.size(); ++i) { diff --git a/core/java/android/transition/Visibility.java b/core/java/android/transition/Visibility.java index f49821f..44f92cd 100644 --- a/core/java/android/transition/Visibility.java +++ b/core/java/android/transition/Visibility.java @@ -30,22 +30,6 @@ import android.view.ViewGroup;   * changes occur. Subclasses should implement one or both of the methods   * {@link #onAppear(ViewGroup, TransitionValues, int, TransitionValues, int)},   * {@link #onDisappear(ViewGroup, TransitionValues, int, TransitionValues, int)}, - * - * <p>Note that a view's visibility change is determined by both whether the view - * itself is changing and whether its parent hierarchy's visibility is changing. - * That is, a view that appears in the end scene will only trigger a call to - * {@link #onAppear(android.view.ViewGroup, TransitionValues, int, TransitionValues, int) - * appear()} if its parent hierarchy was stable between the start and end scenes. - * This is done to avoid causing a visibility transition on every node in a hierarchy - * when only the top-most node is the one that should be transitioned in/out. - * Stability is determined by either the parent hierarchy views being the same - * between scenes or, if scenes are inflated from layout resource files and thus - * have result in different view instances, if the views represented by - * the ids of those parents are stable. This means that visibility determination - * is more effective with inflated view hierarchies if ids are used. - * The exception to this is when the visibility subclass transition is - * targeted at specific views, in which case the visibility of parent views - * is ignored.</p>   */  public abstract class Visibility extends Transition { @@ -111,51 +95,6 @@ public abstract class Visibility extends Transition {          return visibility == View.VISIBLE && parent != null;      } -    /** -     * Tests whether the hierarchy, up to the scene root, changes visibility between -     * start and end scenes. This is done to ensure that a view that changes visibility -     * is only animated if that view's parent was stable between scenes; we should not -     * fade an entire hierarchy, but rather just the top-most node in the hierarchy that -     * changed visibility. Note that both the start and end parents are passed in -     * because the instances may differ for the same view due to layout inflation -     * between scenes. -     * -     * @param sceneRoot The root of the scene hierarchy -     * @param startView The container view in the start scene -     * @param endView The container view in the end scene -     * @return true if the parent hierarchy experienced a visibility change, false -     * otherwise -     */ -    private boolean isHierarchyVisibilityChanging(ViewGroup sceneRoot, ViewGroup startView, -            ViewGroup endView) { - -        if (startView == sceneRoot || endView == sceneRoot) { -            return false; -        } -        TransitionValues startValues = startView != null ? -                getTransitionValues(startView, true) : getTransitionValues(endView, true); -        TransitionValues endValues = endView != null ? -                getTransitionValues(endView, false) : getTransitionValues(startView, false); - -        if (startValues == null || endValues == null) { -            return true; -        } -        Integer visibility = (Integer) startValues.values.get(PROPNAME_VISIBILITY); -        int startVisibility = (visibility != null) ? visibility : -1; -        ViewGroup startParent = (ViewGroup) startValues.values.get(PROPNAME_PARENT); -        visibility = (Integer) endValues.values.get(PROPNAME_VISIBILITY); -        int endVisibility = (visibility != null) ? visibility : -1; -        ViewGroup endParent = (ViewGroup) endValues.values.get(PROPNAME_PARENT); -        if (startVisibility != endVisibility || startParent != endParent) { -            return true; -        } - -        if (startParent != null || endParent != null) { -            return isHierarchyVisibilityChanging(sceneRoot, startParent, endParent); -        } -        return false; -    } -      private VisibilityInfo getVisibilityChangeInfo(TransitionValues startValues,              TransitionValues endValues) {          final VisibilityInfo visInfo = new VisibilityInfo(); @@ -225,9 +164,7 @@ public abstract class Visibility extends Transition {                  int endId = endView != null ? endView.getId() : -1;                  isTarget = isValidTarget(startView, startId) || isValidTarget(endView, endId);              } -            if (isTarget || ((visInfo.startParent != null || visInfo.endParent != null) && -                    !isHierarchyVisibilityChanging(sceneRoot, -                            visInfo.startParent, visInfo.endParent))) { +            if (isTarget || ((visInfo.startParent != null || visInfo.endParent != null))) {                  if (visInfo.fadeIn) {                      return onAppear(sceneRoot, startValues, visInfo.startVisibility,                              endValues, visInfo.endVisibility); diff --git a/core/java/android/widget/ListPopupWindow.java b/core/java/android/widget/ListPopupWindow.java index b7e1fdd..66fe46f 100644 --- a/core/java/android/widget/ListPopupWindow.java +++ b/core/java/android/widget/ListPopupWindow.java @@ -28,6 +28,7 @@ import android.text.TextUtils;  import android.util.AttributeSet;  import android.util.IntProperty;  import android.util.Log; +import android.view.Gravity;  import android.view.KeyEvent;  import android.view.MotionEvent;  import android.view.View; @@ -76,6 +77,8 @@ public class ListPopupWindow {      private int mDropDownVerticalOffset;      private boolean mDropDownVerticalOffsetSet; +    private int mDropDownGravity = Gravity.NO_GRAVITY; +      private boolean mDropDownAlwaysVisible = false;      private boolean mForceIgnoreOutsideTouch = false;      int mListItemExpandMaximum = Integer.MAX_VALUE; @@ -439,6 +442,16 @@ public class ListPopupWindow {      }      /** +     * Set the gravity of the dropdown list. This is commonly used to +     * set gravity to START or END for alignment with the anchor. +     * +     * @param gravity Gravity value to use +     */ +    public void setDropDownGravity(int gravity) { +        mDropDownGravity = gravity; +    } + +    /**       * @return The width of the popup window in pixels.       */      public int getWidth() { @@ -610,7 +623,7 @@ public class ListPopupWindow {              mPopup.setOutsideTouchable(!mForceIgnoreOutsideTouch && !mDropDownAlwaysVisible);              mPopup.setTouchInterceptor(mTouchInterceptor);              mPopup.showAsDropDown(getAnchorView(), -                    mDropDownHorizontalOffset, mDropDownVerticalOffset); +                    mDropDownHorizontalOffset, mDropDownVerticalOffset, mDropDownGravity);              mDropDownList.setSelection(ListView.INVALID_POSITION);              if (!mModal || mDropDownList.isInTouchMode()) { diff --git a/core/java/android/widget/PopupMenu.java b/core/java/android/widget/PopupMenu.java index 9ac6a59..111dadc 100644 --- a/core/java/android/widget/PopupMenu.java +++ b/core/java/android/widget/PopupMenu.java @@ -22,6 +22,7 @@ import com.android.internal.view.menu.MenuPresenter;  import com.android.internal.view.menu.SubMenuBuilder;  import android.content.Context; +import android.view.Gravity;  import android.view.Menu;  import android.view.MenuInflater;  import android.view.MenuItem; @@ -64,12 +65,25 @@ public class PopupMenu implements MenuBuilder.Callback, MenuPresenter.Callback {       *               is room, or above it if there is not.       */      public PopupMenu(Context context, View anchor) { +        this(context, anchor, Gravity.NO_GRAVITY); +    } + +    /** +     * Construct a new PopupMenu. +     * +     * @param context Context for the PopupMenu. +     * @param anchor Anchor view for this popup. The popup will appear below the anchor if there +     *               is room, or above it if there is not. +     * @param gravity The {@link Gravity} value for aligning the popup with its anchor +     */ +    public PopupMenu(Context context, View anchor, int gravity) {          // TODO Theme?          mContext = context;          mMenu = new MenuBuilder(context);          mMenu.setCallback(this);          mAnchor = anchor;          mPopup = new MenuPopupHelper(context, mMenu, anchor); +        mPopup.setGravity(gravity);          mPopup.setCallback(this);      } diff --git a/core/java/android/widget/PopupWindow.java b/core/java/android/widget/PopupWindow.java index 1460737..5663959 100644 --- a/core/java/android/widget/PopupWindow.java +++ b/core/java/android/widget/PopupWindow.java @@ -72,7 +72,9 @@ public class PopupWindow {       * screen as needed, regardless of whether this covers the input method.       */      public static final int INPUT_METHOD_NOT_NEEDED = 2; -     + +    private static final int DEFAULT_ANCHORED_GRAVITY = Gravity.TOP | Gravity.START; +      private Context mContext;      private WindowManager mWindowManager; @@ -135,12 +137,13 @@ public class PopupWindow {                      WindowManager.LayoutParams p = (WindowManager.LayoutParams)                              mPopupView.getLayoutParams(); -                    updateAboveAnchor(findDropDownPosition(anchor, p, mAnchorXoff, mAnchorYoff)); +                    updateAboveAnchor(findDropDownPosition(anchor, p, mAnchorXoff, mAnchorYoff, +                            mAnchoredGravity));                      update(p.x, p.y, -1, -1, true);                  }              }          }; -    private int mAnchorXoff, mAnchorYoff; +    private int mAnchorXoff, mAnchorYoff, mAnchoredGravity;      private boolean mPopupViewInitialLayoutDirectionInherited; @@ -873,15 +876,38 @@ public class PopupWindow {       * location, the popup will be moved correspondingly.</p>       *       * @param anchor the view on which to pin the popup window +     * @param xoff A horizontal offset from the anchor in pixels +     * @param yoff A vertical offset from the anchor in pixels       *       * @see #dismiss()       */      public void showAsDropDown(View anchor, int xoff, int yoff) { +        showAsDropDown(anchor, xoff, yoff, DEFAULT_ANCHORED_GRAVITY); +    } + +    /** +     * <p>Display the content view in a popup window anchored to the bottom-left +     * corner of the anchor view offset by the specified x and y coordinates. +     * If there is not enough room on screen to show +     * the popup in its entirety, this method tries to find a parent scroll +     * view to scroll. If no parent scroll view can be scrolled, the bottom-left +     * corner of the popup is pinned at the top left corner of the anchor view.</p> +     * <p>If the view later scrolls to move <code>anchor</code> to a different +     * location, the popup will be moved correspondingly.</p> +     * +     * @param anchor the view on which to pin the popup window +     * @param xoff A horizontal offset from the anchor in pixels +     * @param yoff A vertical offset from the anchor in pixels +     * @param gravity Alignment of the popup relative to the anchor +     * +     * @see #dismiss() +     */ +    public void showAsDropDown(View anchor, int xoff, int yoff, int gravity) {          if (isShowing() || mContentView == null) {              return;          } -        registerForScrollChanged(anchor, xoff, yoff); +        registerForScrollChanged(anchor, xoff, yoff, gravity);          mIsShowing = true;          mIsDropdown = true; @@ -889,7 +915,7 @@ public class PopupWindow {          WindowManager.LayoutParams p = createPopupLayout(anchor.getWindowToken());          preparePopup(p); -        updateAboveAnchor(findDropDownPosition(anchor, p, xoff, yoff)); +        updateAboveAnchor(findDropDownPosition(anchor, p, xoff, yoff, gravity));          if (mHeightMode < 0) p.height = mLastHeight = mHeightMode;          if (mWidthMode < 0) p.width = mLastWidth = mWidthMode; @@ -1105,17 +1131,24 @@ public class PopupWindow {       * @return true if the popup is translated upwards to fit on screen       */      private boolean findDropDownPosition(View anchor, WindowManager.LayoutParams p, -            int xoff, int yoff) { +            int xoff, int yoff, int gravity) {          final int anchorHeight = anchor.getHeight();          anchor.getLocationInWindow(mDrawingLocation);          p.x = mDrawingLocation[0] + xoff;          p.y = mDrawingLocation[1] + anchorHeight + yoff; + +        final int hgrav = Gravity.getAbsoluteGravity(gravity, anchor.getLayoutDirection()) & +                Gravity.HORIZONTAL_GRAVITY_MASK; +        if (hgrav == Gravity.RIGHT) { +            // Flip the location to align the right sides of the popup and anchor instead of left +            p.x -= mPopupWidth - anchor.getWidth(); +        }          boolean onTop = false; -        p.gravity = Gravity.START | Gravity.TOP; -         +        p.gravity = Gravity.LEFT | Gravity.TOP; +          anchor.getLocationOnScreen(mScreenLocation);          final Rect displayFrame = new Rect();          anchor.getWindowVisibleDisplayFrame(displayFrame); @@ -1141,6 +1174,11 @@ public class PopupWindow {              anchor.getLocationInWindow(mDrawingLocation);              p.x = mDrawingLocation[0] + xoff;              p.y = mDrawingLocation[1] + anchor.getHeight() + yoff; + +            // Preserve the gravity adjustment +            if (hgrav == Gravity.RIGHT) { +                p.x -= mPopupWidth - anchor.getWidth(); +            }              // determine whether there is more space above or below the anchor              anchor.getLocationOnScreen(mScreenLocation); @@ -1148,7 +1186,7 @@ public class PopupWindow {              onTop = (displayFrame.bottom - mScreenLocation[1] - anchor.getHeight() - yoff) <                      (mScreenLocation[1] - yoff - displayFrame.top);              if (onTop) { -                p.gravity = Gravity.START | Gravity.BOTTOM; +                p.gravity = Gravity.LEFT | Gravity.BOTTOM;                  p.y = root.getHeight() - mDrawingLocation[1] + yoff;              } else {                  p.y = mDrawingLocation[1] + anchor.getHeight() + yoff; @@ -1436,7 +1474,7 @@ public class PopupWindow {       * @param height the new height, can be -1 to ignore       */      public void update(View anchor, int width, int height) { -        update(anchor, false, 0, 0, true, width, height); +        update(anchor, false, 0, 0, true, width, height, mAnchoredGravity);      }      /** @@ -1455,11 +1493,11 @@ public class PopupWindow {       * @param height the new height, can be -1 to ignore       */      public void update(View anchor, int xoff, int yoff, int width, int height) { -        update(anchor, true, xoff, yoff, true, width, height); +        update(anchor, true, xoff, yoff, true, width, height, mAnchoredGravity);      }      private void update(View anchor, boolean updateLocation, int xoff, int yoff, -            boolean updateDimension, int width, int height) { +            boolean updateDimension, int width, int height, int gravity) {          if (!isShowing() || mContentView == null) {              return; @@ -1468,11 +1506,12 @@ public class PopupWindow {          WeakReference<View> oldAnchor = mAnchor;          final boolean needsUpdate = updateLocation && (mAnchorXoff != xoff || mAnchorYoff != yoff);          if (oldAnchor == null || oldAnchor.get() != anchor || (needsUpdate && !mIsDropdown)) { -            registerForScrollChanged(anchor, xoff, yoff); +            registerForScrollChanged(anchor, xoff, yoff, gravity);          } else if (needsUpdate) {              // No need to register again if this is a DropDown, showAsDropDown already did.              mAnchorXoff = xoff;              mAnchorYoff = yoff; +            mAnchoredGravity = gravity;          }          WindowManager.LayoutParams p = (WindowManager.LayoutParams) mPopupView.getLayoutParams(); @@ -1494,9 +1533,10 @@ public class PopupWindow {          int y = p.y;          if (updateLocation) { -            updateAboveAnchor(findDropDownPosition(anchor, p, xoff, yoff)); +            updateAboveAnchor(findDropDownPosition(anchor, p, xoff, yoff, gravity));          } else { -            updateAboveAnchor(findDropDownPosition(anchor, p, mAnchorXoff, mAnchorYoff));             +            updateAboveAnchor(findDropDownPosition(anchor, p, mAnchorXoff, mAnchorYoff, +                    mAnchoredGravity));          }          update(p.x, p.y, width, height, x != p.x || y != p.y); @@ -1525,7 +1565,7 @@ public class PopupWindow {          mAnchor = null;      } -    private void registerForScrollChanged(View anchor, int xoff, int yoff) { +    private void registerForScrollChanged(View anchor, int xoff, int yoff, int gravity) {          unregisterForScrollChanged();          mAnchor = new WeakReference<View>(anchor); @@ -1536,6 +1576,7 @@ public class PopupWindow {          mAnchorXoff = xoff;          mAnchorYoff = yoff; +        mAnchoredGravity = gravity;      }      private class PopupViewContainer extends FrameLayout { diff --git a/core/java/com/android/internal/transition/ActionBarTransition.java b/core/java/com/android/internal/transition/ActionBarTransition.java index 8beae8c..c1065e7 100644 --- a/core/java/com/android/internal/transition/ActionBarTransition.java +++ b/core/java/com/android/internal/transition/ActionBarTransition.java @@ -19,7 +19,7 @@ package com.android.internal.transition;  import android.transition.ChangeBounds;  import android.transition.Fade; -import android.transition.TextChange; +import android.transition.ChangeText;  import android.transition.Transition;  import android.transition.TransitionManager;  import android.transition.TransitionSet; @@ -35,8 +35,8 @@ public class ActionBarTransition {      static {          if (TRANSITIONS_ENABLED) { -            final TextChange tc = new TextChange(); -            tc.setChangeBehavior(TextChange.CHANGE_BEHAVIOR_OUT_IN); +            final ChangeText tc = new ChangeText(); +            tc.setChangeBehavior(ChangeText.CHANGE_BEHAVIOR_OUT_IN);              final TransitionSet inner = new TransitionSet();              inner.addTransition(tc).addTransition(new ChangeBounds());              final TransitionSet tg = new TransitionSet(); diff --git a/core/java/com/android/internal/view/menu/ActionMenuPresenter.java b/core/java/com/android/internal/view/menu/ActionMenuPresenter.java index 4c6ddbf..6471e14 100644 --- a/core/java/com/android/internal/view/menu/ActionMenuPresenter.java +++ b/core/java/com/android/internal/view/menu/ActionMenuPresenter.java @@ -25,6 +25,7 @@ import android.transition.Transition;  import android.transition.TransitionManager;  import android.util.SparseBooleanArray;  import android.view.ActionProvider; +import android.view.Gravity;  import android.view.MenuItem;  import android.view.SoundEffectConstants;  import android.view.View; @@ -665,6 +666,7 @@ public class ActionMenuPresenter extends BaseMenuPresenter          public OverflowPopup(Context context, MenuBuilder menu, View anchorView,                  boolean overflowOnly) {              super(context, menu, anchorView, overflowOnly); +            setGravity(Gravity.END);              setCallback(mPopupPresenterCallback);          } diff --git a/core/java/com/android/internal/view/menu/MenuPopupHelper.java b/core/java/com/android/internal/view/menu/MenuPopupHelper.java index dbb78c2..05e9a66 100644 --- a/core/java/com/android/internal/view/menu/MenuPopupHelper.java +++ b/core/java/com/android/internal/view/menu/MenuPopupHelper.java @@ -19,6 +19,7 @@ package com.android.internal.view.menu;  import android.content.Context;  import android.content.res.Resources;  import android.os.Parcelable; +import android.view.Gravity;  import android.view.KeyEvent;  import android.view.LayoutInflater;  import android.view.MenuItem; @@ -69,6 +70,8 @@ public class MenuPopupHelper implements AdapterView.OnItemClickListener, View.On      /** Cached content width from {@link #measureContentWidth}. */      private int mContentWidth; +    private int mDropDownGravity = Gravity.NO_GRAVITY; +      public MenuPopupHelper(Context context, MenuBuilder menu) {          this(context, menu, null, false);      } @@ -102,6 +105,10 @@ public class MenuPopupHelper implements AdapterView.OnItemClickListener, View.On          mForceShowIcon = forceShow;      } +    public void setGravity(int gravity) { +        mDropDownGravity = gravity; +    } +      public void show() {          if (!tryShow()) {              throw new IllegalStateException("MenuPopupHelper cannot be used without an anchor"); @@ -126,6 +133,7 @@ public class MenuPopupHelper implements AdapterView.OnItemClickListener, View.On              if (addGlobalListener) mTreeObserver.addOnGlobalLayoutListener(this);              anchor.addOnAttachStateChangeListener(this);              mPopup.setAnchorView(anchor); +            mPopup.setDropDownGravity(mDropDownGravity);          } else {              return false;          } diff --git a/core/java/com/android/internal/widget/ActionBarView.java b/core/java/com/android/internal/widget/ActionBarView.java index a6566d5..b5d74e8 100644 --- a/core/java/com/android/internal/widget/ActionBarView.java +++ b/core/java/com/android/internal/widget/ActionBarView.java @@ -29,12 +29,6 @@ import android.os.Parcel;  import android.os.Parcelable;  import android.text.Layout;  import android.text.TextUtils; -import android.transition.ChangeBounds; -import android.transition.Fade; -import android.transition.TextChange; -import android.transition.Transition; -import android.transition.TransitionManager; -import android.transition.TransitionSet;  import android.util.AttributeSet;  import android.view.CollapsibleActionView;  import android.view.Gravity;  | 
