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/>
* Classes should implement {@link #preAnimation()} and {@link #postAnimation()}.
* <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.
*
*/
@@ -59,7 +59,7 @@ public abstract class AnimationThread extends Thread {
private final RenderSessionImpl mSession;
Queue<MessageBundle> mQueue = new LinkedList<MessageBundle>();
private Queue<MessageBundle> mQueue = new LinkedList<MessageBundle>();
private final IAnimationListener mListener;
public AnimationThread(RenderSessionImpl scene, String threadName,
@@ -148,6 +148,10 @@ public abstract class AnimationThread extends Thread {
} while (mListener.isCanceled() == false && mQueue.size() > 0);
mListener.done(Status.SUCCESS.createResult());
} catch (Throwable throwable) {
Bridge.getLog().error(null, "Error playing animation", throwable);
} finally {
postAnimation();
Handler_Delegate.setCallback(null);

View File

@@ -50,6 +50,7 @@ import com.android.layoutlib.bridge.android.BridgeXmlBlockParser;
import android.animation.Animator;
import android.animation.AnimatorInflater;
import android.animation.LayoutTransition;
import android.animation.LayoutTransition.TransitionListener;
import android.app.Fragment_Delegate;
import android.graphics.Bitmap;
import android.graphics.Bitmap_Delegate;
@@ -626,7 +627,7 @@ public class RenderSessionImpl {
*
* @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) {
checkLock();
@@ -635,23 +636,43 @@ public class RenderSessionImpl {
LayoutParams layoutParams = null;
if (layoutParamsMap != null) {
// need to create a new LayoutParams object for the new parent.
layoutParams = parentView.generateLayoutParams(
layoutParams = newParentView.generateLayoutParams(
new BridgeLayoutParamsMapAttributes(layoutParamsMap));
}
// get the current parent of the view that needs to be moved.
final ViewGroup previousParent = (ViewGroup) childView.getParent();
if (listener != null) {
final LayoutParams params = layoutParams;
new AnimationThread(this, "moveChild", listener) {
@Override
public Result preAnimation() {
parentView.setLayoutTransition(new LayoutTransition());
return moveView(parentView, childView, index, params);
// set up the transition for the previous parent.
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
public void postAnimation() {
parentView.setLayoutTransition(null);
previousParent.setLayoutTransition(null);
newParentView.setLayoutTransition(null);
}
}.start();
@@ -659,7 +680,7 @@ public class RenderSessionImpl {
return SUCCESS.createResult(layoutParams);
}
Result result = moveView(parentView, childView, index, layoutParams);
Result result = moveView(previousParent, newParentView, childView, index, layoutParams);
if (result.isSuccess() == false) {
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
* 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 index the new location in the new parent
* @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
* 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 {
ViewGroup previousParent = (ViewGroup) view.getParent();
previousParent.removeView(view);
// check if there is a transition on the previousParent.
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) {
parent.addView(view, index, params);
public void startTransition(LayoutTransition transition, ViewGroup container,
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 {
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) {
// looks like this is a view class that doesn't support children manipulation!
return ERROR_VIEWGROUP_NO_CHILDREN.createResult();