am 03d5c6f5: Merge "Add resizeClip attribute to ChangeBounds." into lmp-mr1-dev
* commit '03d5c6f55b316a5b0e1aae405077d1083df60b36': Add resizeClip attribute to ChangeBounds.
This commit is contained in:
@@ -1002,6 +1002,7 @@ package android {
|
||||
field public static final int requiredForAllUsers = 16843728; // 0x10103d0
|
||||
field public static final int requiresFadingEdge = 16843685; // 0x10103a5
|
||||
field public static final int requiresSmallestWidthDp = 16843620; // 0x1010364
|
||||
field public static final int resizeClip = 16844033; // 0x1010501
|
||||
field public static final int resizeMode = 16843619; // 0x1010363
|
||||
field public static final int resizeable = 16843405; // 0x101028d
|
||||
field public static final int resource = 16842789; // 0x1010025
|
||||
@@ -31316,6 +31317,7 @@ package android.transition {
|
||||
ctor public ChangeBounds(android.content.Context, android.util.AttributeSet);
|
||||
method public void captureEndValues(android.transition.TransitionValues);
|
||||
method public void captureStartValues(android.transition.TransitionValues);
|
||||
method public boolean getResizeClip();
|
||||
method public deprecated void setReparent(boolean);
|
||||
method public void setResizeClip(boolean);
|
||||
}
|
||||
|
||||
@@ -18,6 +18,7 @@ package android.transition;
|
||||
|
||||
import android.animation.AnimatorSet;
|
||||
import android.content.Context;
|
||||
import android.content.res.TypedArray;
|
||||
import android.graphics.PointF;
|
||||
|
||||
import android.animation.Animator;
|
||||
@@ -36,6 +37,8 @@ import android.util.Property;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
|
||||
import com.android.internal.R;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
@@ -43,17 +46,20 @@ import java.util.Map;
|
||||
* the scene change and animates those changes during the transition.
|
||||
*
|
||||
* <p>A ChangeBounds transition can be described in a resource file by using the
|
||||
* tag <code>changeBounds</code>, along with the other standard
|
||||
* tag <code>changeBounds</code>, using its attributes of
|
||||
* {@link android.R.styleable#ChangeBounds} along with the other standard
|
||||
* attributes of {@link android.R.styleable#Transition}.</p>
|
||||
*/
|
||||
public class ChangeBounds extends Transition {
|
||||
|
||||
private static final String PROPNAME_BOUNDS = "android:changeBounds:bounds";
|
||||
private static final String PROPNAME_CLIP = "android:changeBounds:clip";
|
||||
private static final String PROPNAME_PARENT = "android:changeBounds:parent";
|
||||
private static final String PROPNAME_WINDOW_X = "android:changeBounds:windowX";
|
||||
private static final String PROPNAME_WINDOW_Y = "android:changeBounds:windowY";
|
||||
private static final String[] sTransitionProperties = {
|
||||
PROPNAME_BOUNDS,
|
||||
PROPNAME_CLIP,
|
||||
PROPNAME_PARENT,
|
||||
PROPNAME_WINDOW_X,
|
||||
PROPNAME_WINDOW_Y
|
||||
@@ -103,6 +109,57 @@ public class ChangeBounds extends Transition {
|
||||
}
|
||||
};
|
||||
|
||||
private static final Property<View, PointF> BOTTOM_RIGHT_ONLY_PROPERTY =
|
||||
new Property<View, PointF>(PointF.class, "bottomRight") {
|
||||
@Override
|
||||
public void set(View view, PointF bottomRight) {
|
||||
int left = view.getLeft();
|
||||
int top = view.getTop();
|
||||
int right = Math.round(bottomRight.x);
|
||||
int bottom = Math.round(bottomRight.y);
|
||||
view.setLeftTopRightBottom(left, top, right, bottom);
|
||||
}
|
||||
|
||||
@Override
|
||||
public PointF get(View view) {
|
||||
return null;
|
||||
}
|
||||
};
|
||||
|
||||
private static final Property<View, PointF> TOP_LEFT_ONLY_PROPERTY =
|
||||
new Property<View, PointF>(PointF.class, "topLeft") {
|
||||
@Override
|
||||
public void set(View view, PointF topLeft) {
|
||||
int left = Math.round(topLeft.x);
|
||||
int top = Math.round(topLeft.y);
|
||||
int right = view.getRight();
|
||||
int bottom = view.getBottom();
|
||||
view.setLeftTopRightBottom(left, top, right, bottom);
|
||||
}
|
||||
|
||||
@Override
|
||||
public PointF get(View view) {
|
||||
return null;
|
||||
}
|
||||
};
|
||||
|
||||
private static final Property<View, PointF> POSITION_PROPERTY =
|
||||
new Property<View, PointF>(PointF.class, "position") {
|
||||
@Override
|
||||
public void set(View view, PointF topLeft) {
|
||||
int left = Math.round(topLeft.x);
|
||||
int top = Math.round(topLeft.y);
|
||||
int right = left + view.getWidth();
|
||||
int bottom = top + view.getHeight();
|
||||
view.setLeftTopRightBottom(left, top, right, bottom);
|
||||
}
|
||||
|
||||
@Override
|
||||
public PointF get(View view) {
|
||||
return null;
|
||||
}
|
||||
};
|
||||
|
||||
int[] tempLocation = new int[2];
|
||||
boolean mResizeClip = false;
|
||||
boolean mReparent = false;
|
||||
@@ -114,6 +171,11 @@ public class ChangeBounds extends Transition {
|
||||
|
||||
public ChangeBounds(Context context, AttributeSet attrs) {
|
||||
super(context, attrs);
|
||||
|
||||
TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.ChangeBounds);
|
||||
boolean resizeClip = a.getBoolean(R.styleable.ChangeBounds_resizeClip, false);
|
||||
a.recycle();
|
||||
setResizeClip(resizeClip);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -121,10 +183,36 @@ public class ChangeBounds extends Transition {
|
||||
return sTransitionProperties;
|
||||
}
|
||||
|
||||
/**
|
||||
* When <code>resizeClip</code> is true, ChangeBounds resizes the view using the clipBounds
|
||||
* instead of changing the dimensions of the view during the animation. When
|
||||
* <code>resizeClip</code> is false, ChangeBounds resizes the View by changing its dimensions.
|
||||
*
|
||||
* <p>When resizeClip is set to true, the clip bounds is modified by ChangeBounds. Therefore,
|
||||
* {@link android.transition.ChangeClipBounds} is not compatible with ChangeBounds
|
||||
* in this mode.</p>
|
||||
*
|
||||
* @param resizeClip Used to indicate whether the view bounds should be modified or the
|
||||
* clip bounds should be modified by ChangeBounds.
|
||||
* @see android.view.View#setClipBounds(android.graphics.Rect)
|
||||
* @attr ref android.R.styleable#ChangeBounds_resizeClip
|
||||
*/
|
||||
public void setResizeClip(boolean resizeClip) {
|
||||
mResizeClip = resizeClip;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true when the ChangeBounds will resize by changing the clip bounds during the
|
||||
* view animation or false when bounds are changed. The default value is false.
|
||||
*
|
||||
* @return true when the ChangeBounds will resize by changing the clip bounds during the
|
||||
* view animation or false when bounds are changed. The default value is false.
|
||||
* @attr ref android.R.styleable#ChangeBounds_resizeClip
|
||||
*/
|
||||
public boolean getResizeClip() {
|
||||
return mResizeClip;
|
||||
}
|
||||
|
||||
/**
|
||||
* Setting this flag tells ChangeBounds to track the before/after parent
|
||||
* of every view using this transition. The flag is not enabled by
|
||||
@@ -153,6 +241,9 @@ public class ChangeBounds extends Transition {
|
||||
values.values.put(PROPNAME_WINDOW_X, tempLocation[0]);
|
||||
values.values.put(PROPNAME_WINDOW_Y, tempLocation[1]);
|
||||
}
|
||||
if (mResizeClip) {
|
||||
values.values.put(PROPNAME_CLIP, view.getClipBounds());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -196,142 +287,149 @@ public class ChangeBounds extends Transition {
|
||||
if (parentMatches(startParent, endParent)) {
|
||||
Rect startBounds = (Rect) startValues.values.get(PROPNAME_BOUNDS);
|
||||
Rect endBounds = (Rect) endValues.values.get(PROPNAME_BOUNDS);
|
||||
int startLeft = startBounds.left;
|
||||
int endLeft = endBounds.left;
|
||||
int startTop = startBounds.top;
|
||||
int endTop = endBounds.top;
|
||||
int startRight = startBounds.right;
|
||||
int endRight = endBounds.right;
|
||||
int startBottom = startBounds.bottom;
|
||||
int endBottom = endBounds.bottom;
|
||||
int startWidth = startRight - startLeft;
|
||||
int startHeight = startBottom - startTop;
|
||||
int endWidth = endRight - endLeft;
|
||||
int endHeight = endBottom - endTop;
|
||||
final int startLeft = startBounds.left;
|
||||
final int endLeft = endBounds.left;
|
||||
final int startTop = startBounds.top;
|
||||
final int endTop = endBounds.top;
|
||||
final int startRight = startBounds.right;
|
||||
final int endRight = endBounds.right;
|
||||
final int startBottom = startBounds.bottom;
|
||||
final int endBottom = endBounds.bottom;
|
||||
final int startWidth = startRight - startLeft;
|
||||
final int startHeight = startBottom - startTop;
|
||||
final int endWidth = endRight - endLeft;
|
||||
final int endHeight = endBottom - endTop;
|
||||
Rect startClip = (Rect) startValues.values.get(PROPNAME_CLIP);
|
||||
Rect endClip = (Rect) endValues.values.get(PROPNAME_CLIP);
|
||||
int numChanges = 0;
|
||||
if ((startWidth != 0 && startHeight != 0) || (endWidth != 0 && endHeight != 0)) {
|
||||
if (startLeft != endLeft || startTop != endTop) ++numChanges;
|
||||
if (startRight != endRight || startBottom != endBottom) ++numChanges;
|
||||
}
|
||||
if ((startClip != null && !startClip.equals(endClip)) ||
|
||||
(startClip == null && endClip != null)) {
|
||||
++numChanges;
|
||||
}
|
||||
if (numChanges > 0) {
|
||||
Animator anim;
|
||||
if (!mResizeClip) {
|
||||
view.setLeftTopRightBottom(startLeft, startTop, startRight, startBottom);
|
||||
ViewBounds viewBounds = new ViewBounds(view);
|
||||
Path topLeftPath = getPathMotion().getPath(startLeft, startTop,
|
||||
endLeft, endTop);
|
||||
ObjectAnimator topLeftAnimator = ObjectAnimator
|
||||
.ofObject(viewBounds, TOP_LEFT_PROPERTY, null, topLeftPath);
|
||||
if (numChanges == 2) {
|
||||
if (startWidth == endWidth && startHeight == endHeight) {
|
||||
Path topLeftPath = getPathMotion().getPath(startLeft, startTop, endLeft,
|
||||
endTop);
|
||||
anim = ObjectAnimator.ofObject(view, POSITION_PROPERTY, null,
|
||||
topLeftPath);
|
||||
} else {
|
||||
final ViewBounds viewBounds = new ViewBounds(view);
|
||||
Path topLeftPath = getPathMotion().getPath(startLeft, startTop,
|
||||
endLeft, endTop);
|
||||
ObjectAnimator topLeftAnimator = ObjectAnimator
|
||||
.ofObject(viewBounds, TOP_LEFT_PROPERTY, null, topLeftPath);
|
||||
|
||||
Path bottomRightPath = getPathMotion().getPath(startRight, startBottom,
|
||||
endRight, endBottom);
|
||||
ObjectAnimator bottomRightAnimator = ObjectAnimator.ofObject(viewBounds,
|
||||
BOTTOM_RIGHT_PROPERTY, null, bottomRightPath);
|
||||
AnimatorSet anim = new AnimatorSet();
|
||||
anim.playTogether(topLeftAnimator, bottomRightAnimator);
|
||||
|
||||
if (view.getParent() instanceof ViewGroup) {
|
||||
final ViewGroup parent = (ViewGroup) view.getParent();
|
||||
parent.suppressLayout(true);
|
||||
TransitionListener transitionListener = new TransitionListenerAdapter() {
|
||||
boolean mCanceled = false;
|
||||
|
||||
@Override
|
||||
public void onTransitionCancel(Transition transition) {
|
||||
parent.suppressLayout(false);
|
||||
mCanceled = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onTransitionEnd(Transition transition) {
|
||||
if (!mCanceled) {
|
||||
parent.suppressLayout(false);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onTransitionPause(Transition transition) {
|
||||
parent.suppressLayout(false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onTransitionResume(Transition transition) {
|
||||
parent.suppressLayout(true);
|
||||
}
|
||||
};
|
||||
addListener(transitionListener);
|
||||
Path bottomRightPath = getPathMotion().getPath(startRight, startBottom,
|
||||
endRight, endBottom);
|
||||
ObjectAnimator bottomRightAnimator = ObjectAnimator.ofObject(viewBounds,
|
||||
BOTTOM_RIGHT_PROPERTY, null, bottomRightPath);
|
||||
AnimatorSet set = new AnimatorSet();
|
||||
set.playTogether(topLeftAnimator, bottomRightAnimator);
|
||||
anim = set;
|
||||
set.addListener(new AnimatorListenerAdapter() {
|
||||
// We need a strong reference to viewBounds until the
|
||||
// animator ends.
|
||||
private ViewBounds mViewBounds = viewBounds;
|
||||
});
|
||||
}
|
||||
} else if (startLeft != endLeft || startTop != endTop) {
|
||||
Path topLeftPath = getPathMotion().getPath(startLeft, startTop,
|
||||
endLeft, endTop);
|
||||
anim = ObjectAnimator.ofObject(view, TOP_LEFT_ONLY_PROPERTY, null,
|
||||
topLeftPath);
|
||||
} else {
|
||||
Path bottomRight = getPathMotion().getPath(startRight, startBottom,
|
||||
endRight, endBottom);
|
||||
anim = ObjectAnimator.ofObject(view, BOTTOM_RIGHT_ONLY_PROPERTY, null,
|
||||
bottomRight);
|
||||
}
|
||||
return anim;
|
||||
} else {
|
||||
if (startWidth != endWidth) view.setRight(endLeft +
|
||||
Math.max(startWidth, endWidth));
|
||||
if (startHeight != endHeight) view.setBottom(endTop +
|
||||
Math.max(startHeight, endHeight));
|
||||
// TODO: don't clobber TX/TY
|
||||
if (startLeft != endLeft) view.setTranslationX(startLeft - endLeft);
|
||||
if (startTop != endTop) view.setTranslationY(startTop - endTop);
|
||||
// Animate location with translationX/Y and size with clip bounds
|
||||
float transXDelta = endLeft - startLeft;
|
||||
float transYDelta = endTop - startTop;
|
||||
int widthDelta = endWidth - startWidth;
|
||||
int heightDelta = endHeight - startHeight;
|
||||
numChanges = 0;
|
||||
if (transXDelta != 0) numChanges++;
|
||||
if (transYDelta != 0) numChanges++;
|
||||
if (widthDelta != 0 || heightDelta != 0) numChanges++;
|
||||
ObjectAnimator translationAnimator = null;
|
||||
if (transXDelta != 0 || transYDelta != 0) {
|
||||
Path topLeftPath = getPathMotion().getPath(0, 0, transXDelta, transYDelta);
|
||||
translationAnimator = ObjectAnimator.ofFloat(view, View.TRANSLATION_X,
|
||||
View.TRANSLATION_Y, topLeftPath);
|
||||
int maxWidth = Math.max(startWidth, endWidth);
|
||||
int maxHeight = Math.max(startHeight, endHeight);
|
||||
|
||||
view.setLeftTopRightBottom(startLeft, startTop, startLeft + maxWidth,
|
||||
startTop + maxHeight);
|
||||
|
||||
ObjectAnimator positionAnimator = null;
|
||||
if (startLeft != endLeft || startTop != endTop) {
|
||||
Path topLeftPath = getPathMotion().getPath(startLeft, startTop, endLeft,
|
||||
endTop);
|
||||
positionAnimator = ObjectAnimator.ofObject(view, POSITION_PROPERTY, null,
|
||||
topLeftPath);
|
||||
}
|
||||
final Rect finalClip = endClip;
|
||||
if (startClip == null) {
|
||||
startClip = new Rect(0, 0, startWidth, startHeight);
|
||||
}
|
||||
if (endClip == null) {
|
||||
endClip = new Rect(0, 0, endWidth, endHeight);
|
||||
}
|
||||
ObjectAnimator clipAnimator = null;
|
||||
if (widthDelta != 0 || heightDelta != 0) {
|
||||
Rect tempStartBounds = new Rect(0, 0, startWidth, startHeight);
|
||||
Rect tempEndBounds = new Rect(0, 0, endWidth, endHeight);
|
||||
if (!startClip.equals(endClip)) {
|
||||
view.setClipBounds(startClip);
|
||||
clipAnimator = ObjectAnimator.ofObject(view, "clipBounds", sRectEvaluator,
|
||||
tempStartBounds, tempEndBounds);
|
||||
}
|
||||
Animator anim = TransitionUtils.mergeAnimators(translationAnimator,
|
||||
clipAnimator);
|
||||
if (view.getParent() instanceof ViewGroup) {
|
||||
final ViewGroup parent = (ViewGroup) view.getParent();
|
||||
parent.suppressLayout(true);
|
||||
TransitionListener transitionListener = new TransitionListenerAdapter() {
|
||||
boolean mCanceled = false;
|
||||
startClip, endClip);
|
||||
clipAnimator.addListener(new AnimatorListenerAdapter() {
|
||||
private boolean mIsCanceled;
|
||||
|
||||
@Override
|
||||
public void onTransitionCancel(Transition transition) {
|
||||
parent.suppressLayout(false);
|
||||
mCanceled = true;
|
||||
public void onAnimationCancel(Animator animation) {
|
||||
mIsCanceled = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onTransitionEnd(Transition transition) {
|
||||
if (!mCanceled) {
|
||||
parent.suppressLayout(false);
|
||||
public void onAnimationEnd(Animator animation) {
|
||||
if (!mIsCanceled) {
|
||||
view.setClipBounds(finalClip);
|
||||
view.setLeftTopRightBottom(endLeft, endTop, endRight,
|
||||
endBottom);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
anim = TransitionUtils.mergeAnimators(positionAnimator,
|
||||
clipAnimator);
|
||||
}
|
||||
if (view.getParent() instanceof ViewGroup) {
|
||||
final ViewGroup parent = (ViewGroup) view.getParent();
|
||||
parent.suppressLayout(true);
|
||||
TransitionListener transitionListener = new TransitionListenerAdapter() {
|
||||
boolean mCanceled = false;
|
||||
|
||||
@Override
|
||||
public void onTransitionPause(Transition transition) {
|
||||
@Override
|
||||
public void onTransitionCancel(Transition transition) {
|
||||
parent.suppressLayout(false);
|
||||
mCanceled = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onTransitionEnd(Transition transition) {
|
||||
if (!mCanceled) {
|
||||
parent.suppressLayout(false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onTransitionResume(Transition transition) {
|
||||
parent.suppressLayout(true);
|
||||
}
|
||||
};
|
||||
addListener(transitionListener);
|
||||
}
|
||||
anim.addListener(new AnimatorListenerAdapter() {
|
||||
@Override
|
||||
public void onAnimationEnd(Animator animation) {
|
||||
view.setClipBounds(null);
|
||||
}
|
||||
});
|
||||
return anim;
|
||||
|
||||
@Override
|
||||
public void onTransitionPause(Transition transition) {
|
||||
parent.suppressLayout(false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onTransitionResume(Transition transition) {
|
||||
parent.suppressLayout(true);
|
||||
}
|
||||
};
|
||||
addListener(transitionListener);
|
||||
}
|
||||
return anim;
|
||||
}
|
||||
} else {
|
||||
int startX = (Integer) startValues.values.get(PROPNAME_WINDOW_X);
|
||||
|
||||
@@ -15691,7 +15691,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
|
||||
sizeChange(newWidth, newHeight, oldWidth, oldHeight);
|
||||
}
|
||||
|
||||
if ((mViewFlags & VISIBILITY_MASK) == VISIBLE) {
|
||||
if ((mViewFlags & VISIBILITY_MASK) == VISIBLE || mGhostView != null) {
|
||||
// If we are visible, force the DRAWN bit to on so that
|
||||
// this invalidate will go through (at least to our parent).
|
||||
// This is because someone may have invalidated this view
|
||||
|
||||
@@ -5702,6 +5702,17 @@
|
||||
<attr name="reparent" format="boolean"/>
|
||||
</declare-styleable>
|
||||
|
||||
<!-- Use <code>changeBounds</code>as the root tag of the XML resource that
|
||||
describes a {@link android.transition.ChangeBounds} transition.
|
||||
The attributes of the {@link android.R.styleable#Transition Transition}
|
||||
resource are available in addition to the specific attributes of ChangeBounds
|
||||
described here. -->
|
||||
<declare-styleable name="ChangeBounds">
|
||||
<!-- Resize the view by adjusting the clipBounds rather than changing the
|
||||
dimensions of the view itself. The default value is false. -->
|
||||
<attr name="resizeClip" format="boolean"/>
|
||||
</declare-styleable>
|
||||
|
||||
<!-- Use <code>transitionManager</code> as the root tag of the XML resource that
|
||||
describes a {@link android.transition.TransitionManager
|
||||
TransitionManager}. -->
|
||||
|
||||
@@ -2589,5 +2589,6 @@
|
||||
|
||||
<!-- @hide -->
|
||||
<public-padding type="attr" name="private_resource_pad" end="0x01010500" />
|
||||
<public type="attr" name="resizeClip"/>
|
||||
|
||||
</resources>
|
||||
|
||||
Reference in New Issue
Block a user