Merge "LayoutLib: fix animated moveChild." into honeycomb

This commit is contained in:
Xavier Ducrohet
2011-01-07 13:54:26 -08:00
committed by Android (Google) Code Review
2 changed files with 80 additions and 18 deletions

View File

@@ -39,7 +39,7 @@ import java.util.Queue;
* <p/> * <p/>
* Classes should implement {@link #preAnimation()} and {@link #postAnimation()}. * Classes should implement {@link #preAnimation()} and {@link #postAnimation()}.
* <p/> * <p/>
* If {@link #preAnimation()} does not start an animation something then the thread doesn't do * If {@link #preAnimation()} does not start an animation somehow then the thread doesn't do
* anything. * anything.
* *
*/ */
@@ -59,7 +59,7 @@ public abstract class AnimationThread extends Thread {
private final RenderSessionImpl mSession; private final RenderSessionImpl mSession;
Queue<MessageBundle> mQueue = new LinkedList<MessageBundle>(); private Queue<MessageBundle> mQueue = new LinkedList<MessageBundle>();
private final IAnimationListener mListener; private final IAnimationListener mListener;
public AnimationThread(RenderSessionImpl scene, String threadName, public AnimationThread(RenderSessionImpl scene, String threadName,
@@ -148,6 +148,10 @@ public abstract class AnimationThread extends Thread {
} while (mListener.isCanceled() == false && mQueue.size() > 0); } while (mListener.isCanceled() == false && mQueue.size() > 0);
mListener.done(Status.SUCCESS.createResult()); mListener.done(Status.SUCCESS.createResult());
} catch (Throwable throwable) {
Bridge.getLog().error(null, "Error playing animation", throwable);
} finally { } finally {
postAnimation(); postAnimation();
Handler_Delegate.setCallback(null); Handler_Delegate.setCallback(null);

View File

@@ -50,6 +50,7 @@ import com.android.layoutlib.bridge.android.BridgeXmlBlockParser;
import android.animation.Animator; import android.animation.Animator;
import android.animation.AnimatorInflater; import android.animation.AnimatorInflater;
import android.animation.LayoutTransition; import android.animation.LayoutTransition;
import android.animation.LayoutTransition.TransitionListener;
import android.app.Fragment_Delegate; import android.app.Fragment_Delegate;
import android.graphics.Bitmap; import android.graphics.Bitmap;
import android.graphics.Bitmap_Delegate; import android.graphics.Bitmap_Delegate;
@@ -626,7 +627,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 parentView, 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, IAnimationListener listener) {
checkLock(); checkLock();
@@ -635,23 +636,43 @@ public class RenderSessionImpl {
LayoutParams layoutParams = null; LayoutParams layoutParams = null;
if (layoutParamsMap != null) { if (layoutParamsMap != null) {
// need to create a new LayoutParams object for the new parent. // need to create a new LayoutParams object for the new parent.
layoutParams = parentView.generateLayoutParams( layoutParams = newParentView.generateLayoutParams(
new BridgeLayoutParamsMapAttributes(layoutParamsMap)); new BridgeLayoutParamsMapAttributes(layoutParamsMap));
} }
// get the current parent of the view that needs to be moved.
final ViewGroup previousParent = (ViewGroup) childView.getParent();
if (listener != null) { if (listener != null) {
final LayoutParams params = layoutParams; final LayoutParams params = layoutParams;
new AnimationThread(this, "moveChild", listener) { new AnimationThread(this, "moveChild", listener) {
@Override @Override
public Result preAnimation() { public Result preAnimation() {
parentView.setLayoutTransition(new LayoutTransition()); // set up the transition for the previous parent.
return moveView(parentView, childView, index, params); LayoutTransition removeTransition = new LayoutTransition();
previousParent.setLayoutTransition(removeTransition);
// no fade-out
removeTransition.setAnimator(LayoutTransition.DISAPPEARING, null);
// now for the new parent, if different
if (previousParent != newParentView) {
LayoutTransition addTransition = new LayoutTransition();
// no fade-in
addTransition.setAnimator(LayoutTransition.APPEARING, null);
newParentView.setLayoutTransition(addTransition);
}
return moveView(previousParent, newParentView, childView, index, params);
} }
@Override @Override
public void postAnimation() { public void postAnimation() {
parentView.setLayoutTransition(null); previousParent.setLayoutTransition(null);
newParentView.setLayoutTransition(null);
} }
}.start(); }.start();
@@ -659,7 +680,7 @@ public class RenderSessionImpl {
return SUCCESS.createResult(layoutParams); return SUCCESS.createResult(layoutParams);
} }
Result result = moveView(parentView, childView, index, layoutParams); Result result = moveView(previousParent, newParentView, childView, index, layoutParams);
if (result.isSuccess() == false) { if (result.isSuccess() == false) {
return result; return result;
} }
@@ -676,7 +697,8 @@ public class RenderSessionImpl {
* Moves a View from its current parent to a new given parent at a new given location, with * Moves a View from its current parent to a new given parent at a new given location, with
* an optional new {@link LayoutParams} instance * an optional new {@link LayoutParams} instance
* *
* @param parent the new parent * @param previousParent the previous parent, still owning the child at the time of the call.
* @param newParent the new parent
* @param view the view to move * @param view 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.
@@ -685,20 +707,56 @@ 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 parent, View view, int index, LayoutParams params) { private Result moveView(ViewGroup previousParent, final ViewGroup newParent, View view,
final int index, final LayoutParams params) {
try { try {
ViewGroup previousParent = (ViewGroup) view.getParent(); // check if there is a transition on the previousParent.
previousParent.removeView(view); LayoutTransition transition = previousParent.getLayoutTransition();
if (transition != null) {
// in this case there is an animation. This means we have to listener for the
// disappearing animation to be done before we can add the view to the new parent.
// TODO: check that if the disappearing animation is null, the removal is done during the removeView call which would simplify the code.
// add it to the parentView in the correct location // add a listener to the transition to be notified of the actual removal.
transition.addTransitionListener(new TransitionListener() {
if (params != null) { public void startTransition(LayoutTransition transition, ViewGroup container,
parent.addView(view, index, params); View view, int transitionType) {
// don't care.
}
public void endTransition(LayoutTransition transition, ViewGroup container,
View view, int transitionType) {
if (transitionType == LayoutTransition.DISAPPEARING) {
// add it to the parentView in the correct location
if (params != null) {
newParent.addView(view, index, params);
} else {
newParent.addView(view, index);
}
}
}
});
// remove the view from the current parent.
previousParent.removeView(view);
// and return since adding the view to the new parent is done in the listener.
return SUCCESS.createResult();
} else { } else {
parent.addView(view, index); // standard code with no animation. pretty simple.
} previousParent.removeView(view);
return SUCCESS.createResult(); // add it to the parentView in the correct location
if (params != null) {
newParent.addView(view, index, params);
} else {
newParent.addView(view, index);
}
return SUCCESS.createResult();
}
} catch (UnsupportedOperationException e) { } catch (UnsupportedOperationException e) {
// looks like this is a view class that doesn't support children manipulation! // looks like this is a view class that doesn't support children manipulation!
return ERROR_VIEWGROUP_NO_CHILDREN.createResult(); return ERROR_VIEWGROUP_NO_CHILDREN.createResult();