am 0f83b571: Merge "LayoutLib: Fix moveChild animation." into honeycomb
* commit '0f83b571e294a443a992cdf71bc5e6aaf7464d39': LayoutLib: Fix moveChild animation.
This commit is contained in:
@@ -195,7 +195,8 @@ public final class Bridge extends com.android.ide.common.rendering.api.Bridge {
|
|||||||
Capability.RENDER,
|
Capability.RENDER,
|
||||||
Capability.EMBEDDED_LAYOUT,
|
Capability.EMBEDDED_LAYOUT,
|
||||||
Capability.VIEW_MANIPULATION,
|
Capability.VIEW_MANIPULATION,
|
||||||
Capability.ANIMATE);
|
Capability.PLAY_ANIMATION,
|
||||||
|
Capability.ANIMATED_VIEW_MANIPULATION);
|
||||||
|
|
||||||
|
|
||||||
BridgeAssetManager.initSystem();
|
BridgeAssetManager.initSystem();
|
||||||
|
|||||||
@@ -28,7 +28,7 @@ import android.os.Handler_Delegate;
|
|||||||
import android.os.Message;
|
import android.os.Message;
|
||||||
import android.os.Handler_Delegate.IHandlerCallback;
|
import android.os.Handler_Delegate.IHandlerCallback;
|
||||||
|
|
||||||
import java.util.LinkedList;
|
import java.util.PriorityQueue;
|
||||||
import java.util.Queue;
|
import java.util.Queue;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -45,7 +45,7 @@ import java.util.Queue;
|
|||||||
*/
|
*/
|
||||||
public abstract class AnimationThread extends Thread {
|
public abstract class AnimationThread extends Thread {
|
||||||
|
|
||||||
private static class MessageBundle {
|
private static class MessageBundle implements Comparable<MessageBundle> {
|
||||||
final Handler mTarget;
|
final Handler mTarget;
|
||||||
final Message mMessage;
|
final Message mMessage;
|
||||||
final long mUptimeMillis;
|
final long mUptimeMillis;
|
||||||
@@ -55,11 +55,18 @@ public abstract class AnimationThread extends Thread {
|
|||||||
mMessage = message;
|
mMessage = message;
|
||||||
mUptimeMillis = uptimeMillis;
|
mUptimeMillis = uptimeMillis;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public int compareTo(MessageBundle bundle) {
|
||||||
|
if (mUptimeMillis < bundle.mUptimeMillis) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private final RenderSessionImpl mSession;
|
private final RenderSessionImpl mSession;
|
||||||
|
|
||||||
private Queue<MessageBundle> mQueue = new LinkedList<MessageBundle>();
|
private Queue<MessageBundle> mQueue = new PriorityQueue<MessageBundle>();
|
||||||
private final IAnimationListener mListener;
|
private final IAnimationListener mListener;
|
||||||
|
|
||||||
public AnimationThread(RenderSessionImpl scene, String threadName,
|
public AnimationThread(RenderSessionImpl scene, String threadName,
|
||||||
|
|||||||
@@ -630,7 +630,7 @@ public class RenderSessionImpl {
|
|||||||
* @see LayoutScene#moveChild(Object, Object, int, Map, IAnimationListener)
|
* @see LayoutScene#moveChild(Object, Object, int, Map, IAnimationListener)
|
||||||
*/
|
*/
|
||||||
public Result moveChild(final ViewGroup newParentView, final View childView, final int index,
|
public Result moveChild(final ViewGroup newParentView, final View childView, final int index,
|
||||||
Map<String, String> layoutParamsMap, IAnimationListener listener) {
|
Map<String, String> layoutParamsMap, final IAnimationListener listener) {
|
||||||
checkLock();
|
checkLock();
|
||||||
|
|
||||||
invalidateRenderingSize();
|
invalidateRenderingSize();
|
||||||
@@ -647,42 +647,73 @@ public class RenderSessionImpl {
|
|||||||
|
|
||||||
if (listener != null) {
|
if (listener != null) {
|
||||||
final LayoutParams params = layoutParams;
|
final LayoutParams params = layoutParams;
|
||||||
new AnimationThread(this, "moveChild", listener) {
|
|
||||||
|
|
||||||
@Override
|
// there is no support for animating views across layouts, so in case the new and old
|
||||||
public Result preAnimation() {
|
// parent views are different we fake the animation through a no animation thread.
|
||||||
// set up the transition for the previous parent.
|
if (previousParent != newParentView) {
|
||||||
LayoutTransition removeTransition = new LayoutTransition();
|
new Thread("not animated moveChild") {
|
||||||
previousParent.setLayoutTransition(removeTransition);
|
@Override
|
||||||
|
public void run() {
|
||||||
|
Result result = moveView(previousParent, newParentView, childView, index,
|
||||||
|
params);
|
||||||
|
if (result.isSuccess() == false) {
|
||||||
|
listener.done(result);
|
||||||
|
}
|
||||||
|
|
||||||
// no fade-out. Because we can't rely on layout transition listeners when
|
// ready to do the work, acquire the scene.
|
||||||
// there is no Animator at all, instead we keep the animator but set its
|
result = acquire(250);
|
||||||
// duration to 0.
|
if (result.isSuccess() == false) {
|
||||||
// Note: Cannot user Animation.setDuration() directly. Have to set it
|
listener.done(result);
|
||||||
// on the LayoutTransition.
|
return;
|
||||||
removeTransition.setDuration(LayoutTransition.DISAPPEARING, 0);
|
}
|
||||||
|
|
||||||
if (previousParent != newParentView) {
|
try {
|
||||||
// different parent, set a Layout transition on the new parent.
|
result = render();
|
||||||
newParentView.setLayoutTransition(new LayoutTransition());
|
if (result.isSuccess()) {
|
||||||
|
listener.onNewFrame(RenderSessionImpl.this.getSession());
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
release();
|
||||||
|
}
|
||||||
|
|
||||||
|
listener.done(result);
|
||||||
|
}
|
||||||
|
}.start();
|
||||||
|
} else {
|
||||||
|
new AnimationThread(this, "moveChild", listener) {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Result preAnimation() {
|
||||||
|
// set up the transition for the parent.
|
||||||
|
LayoutTransition transition = new LayoutTransition();
|
||||||
|
previousParent.setLayoutTransition(transition);
|
||||||
|
|
||||||
|
// tweak the animation durations and start delays (to match the duration of
|
||||||
|
// animation playing just before).
|
||||||
|
// Note: Cannot user Animation.setDuration() directly. Have to set it
|
||||||
|
// on the LayoutTransition.
|
||||||
|
transition.setDuration(LayoutTransition.DISAPPEARING, 100);
|
||||||
|
// CHANGE_DISAPPEARING plays after DISAPPEARING
|
||||||
|
transition.setStartDelay(LayoutTransition.CHANGE_DISAPPEARING, 100);
|
||||||
|
|
||||||
|
transition.setDuration(LayoutTransition.CHANGE_DISAPPEARING, 100);
|
||||||
|
|
||||||
|
transition.setDuration(LayoutTransition.CHANGE_APPEARING, 100);
|
||||||
|
// CHANGE_APPEARING plays after CHANGE_APPEARING
|
||||||
|
transition.setStartDelay(LayoutTransition.APPEARING, 100);
|
||||||
|
|
||||||
|
transition.setDuration(LayoutTransition.APPEARING, 100);
|
||||||
|
|
||||||
|
return moveView(previousParent, newParentView, childView, index, params);
|
||||||
}
|
}
|
||||||
|
|
||||||
// no fade-in. Because we can't rely on layout transition listeners when
|
@Override
|
||||||
// there is no Animator at all, instead we keep the animator but set its
|
public void postAnimation() {
|
||||||
// duration to 0.
|
previousParent.setLayoutTransition(null);
|
||||||
// Note: Cannot user Animation.setDuration() directly. Have to set it
|
newParentView.setLayoutTransition(null);
|
||||||
// on the LayoutTransition.
|
}
|
||||||
newParentView.getLayoutTransition().setDuration(LayoutTransition.APPEARING, 0);
|
}.start();
|
||||||
|
}
|
||||||
return moveView(previousParent, newParentView, childView, index, params);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void postAnimation() {
|
|
||||||
previousParent.setLayoutTransition(null);
|
|
||||||
newParentView.setLayoutTransition(null);
|
|
||||||
}
|
|
||||||
}.start();
|
|
||||||
|
|
||||||
// always return success since the real status will come through the listener.
|
// always return success since the real status will come through the listener.
|
||||||
return SUCCESS.createResult(layoutParams);
|
return SUCCESS.createResult(layoutParams);
|
||||||
@@ -707,7 +738,7 @@ public class RenderSessionImpl {
|
|||||||
*
|
*
|
||||||
* @param previousParent the previous parent, still owning the child at the time of the call.
|
* @param previousParent the previous parent, still owning the child at the time of the call.
|
||||||
* @param newParent the new parent
|
* @param newParent the new parent
|
||||||
* @param view the view to move
|
* @param movedView the view to move
|
||||||
* @param index the new location in the new parent
|
* @param index the new location in the new parent
|
||||||
* @param params an option (can be null) {@link LayoutParams} instance.
|
* @param params an option (can be null) {@link LayoutParams} instance.
|
||||||
*
|
*
|
||||||
@@ -715,12 +746,12 @@ public class RenderSessionImpl {
|
|||||||
* {@link Status#ERROR_VIEWGROUP_NO_CHILDREN} if the given parent doesn't support
|
* {@link Status#ERROR_VIEWGROUP_NO_CHILDREN} if the given parent doesn't support
|
||||||
* adding views.
|
* adding views.
|
||||||
*/
|
*/
|
||||||
private Result moveView(ViewGroup previousParent, final ViewGroup newParent, View view,
|
private Result moveView(ViewGroup previousParent, final ViewGroup newParent,
|
||||||
final int index, final LayoutParams params) {
|
final View movedView, final int index, final LayoutParams params) {
|
||||||
try {
|
try {
|
||||||
// check if there is a transition on the previousParent.
|
// check if there is a transition on the previousParent.
|
||||||
LayoutTransition transition = previousParent.getLayoutTransition();
|
LayoutTransition previousTransition = previousParent.getLayoutTransition();
|
||||||
if (transition != null) {
|
if (previousTransition != null) {
|
||||||
// in this case there is an animation. This means we have to wait for the child's
|
// in this case there is an animation. This means we have to wait for the child's
|
||||||
// parent reference to be null'ed out so that we can add it to the new parent.
|
// parent reference to be null'ed out so that we can add it to the new parent.
|
||||||
// It is technically removed right before the DISAPPEARING animation is done (if
|
// It is technically removed right before the DISAPPEARING animation is done (if
|
||||||
@@ -730,48 +761,50 @@ public class RenderSessionImpl {
|
|||||||
// parent, we need to wait until the CHANGE_DISAPPEARING animation is done before
|
// parent, we need to wait until the CHANGE_DISAPPEARING animation is done before
|
||||||
// adding the child or the child will appear in its new location before the
|
// adding the child or the child will appear in its new location before the
|
||||||
// other children have made room for it.
|
// other children have made room for it.
|
||||||
// If the parents are different, then we can add the child to its new parent right
|
|
||||||
// after the DISAPPEARING animation is done.
|
|
||||||
|
|
||||||
final int waitForType = newParent == previousParent ?
|
|
||||||
LayoutTransition.CHANGE_DISAPPEARING : LayoutTransition.DISAPPEARING;
|
|
||||||
|
|
||||||
// add a listener to the transition to be notified of the actual removal.
|
// add a listener to the transition to be notified of the actual removal.
|
||||||
transition.addTransitionListener(new TransitionListener() {
|
previousTransition.addTransitionListener(new TransitionListener() {
|
||||||
|
private int mChangeDisappearingCount = 0;
|
||||||
|
|
||||||
public void startTransition(LayoutTransition transition, ViewGroup container,
|
public void startTransition(LayoutTransition transition, ViewGroup container,
|
||||||
View view, int transitionType) {
|
View view, int transitionType) {
|
||||||
// don't care.
|
if (transitionType == LayoutTransition.CHANGE_DISAPPEARING) {
|
||||||
|
mChangeDisappearingCount++;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void endTransition(LayoutTransition transition, ViewGroup container,
|
public void endTransition(LayoutTransition transition, ViewGroup container,
|
||||||
View view, int transitionType) {
|
View view, int transitionType) {
|
||||||
if (transitionType == waitForType) {
|
if (transitionType == LayoutTransition.CHANGE_DISAPPEARING) {
|
||||||
|
mChangeDisappearingCount--;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (transitionType == LayoutTransition.CHANGE_DISAPPEARING &&
|
||||||
|
mChangeDisappearingCount == 0) {
|
||||||
// add it to the parentView in the correct location
|
// add it to the parentView in the correct location
|
||||||
if (params != null) {
|
if (params != null) {
|
||||||
newParent.addView(view, index, params);
|
newParent.addView(movedView, index, params);
|
||||||
} else {
|
} else {
|
||||||
newParent.addView(view, index);
|
newParent.addView(movedView, index);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
// remove the view from the current parent.
|
// remove the view from the current parent.
|
||||||
previousParent.removeView(view);
|
previousParent.removeView(movedView);
|
||||||
|
|
||||||
// and return since adding the view to the new parent is done in the listener.
|
// and return since adding the view to the new parent is done in the listener.
|
||||||
return SUCCESS.createResult();
|
return SUCCESS.createResult();
|
||||||
} else {
|
} else {
|
||||||
// standard code with no animation. pretty simple.
|
// standard code with no animation. pretty simple.
|
||||||
previousParent.removeView(view);
|
previousParent.removeView(movedView);
|
||||||
|
|
||||||
// add it to the parentView in the correct location
|
// add it to the parentView in the correct location
|
||||||
if (params != null) {
|
if (params != null) {
|
||||||
newParent.addView(view, index, params);
|
newParent.addView(movedView, index, params);
|
||||||
} else {
|
} else {
|
||||||
newParent.addView(view, index);
|
newParent.addView(movedView, index);
|
||||||
}
|
}
|
||||||
|
|
||||||
return SUCCESS.createResult();
|
return SUCCESS.createResult();
|
||||||
|
|||||||
Reference in New Issue
Block a user