Make fragment animations work when fragments go away
Change-Id: I136de6ef910cc02b8181fcfa065bdb0770841396
This commit is contained in:
@@ -202631,6 +202631,19 @@
|
||||
<parameter name="drawingTime" type="long">
|
||||
</parameter>
|
||||
</method>
|
||||
<method name="endViewTransition"
|
||||
return="void"
|
||||
abstract="false"
|
||||
native="false"
|
||||
synchronized="false"
|
||||
static="false"
|
||||
final="false"
|
||||
deprecated="not deprecated"
|
||||
visibility="public"
|
||||
>
|
||||
<parameter name="view" type="android.view.View">
|
||||
</parameter>
|
||||
</method>
|
||||
<method name="focusSearch"
|
||||
return="android.view.View"
|
||||
abstract="false"
|
||||
@@ -203528,6 +203541,19 @@
|
||||
visibility="public"
|
||||
>
|
||||
</method>
|
||||
<method name="startViewTransition"
|
||||
return="void"
|
||||
abstract="false"
|
||||
native="false"
|
||||
synchronized="false"
|
||||
static="false"
|
||||
final="false"
|
||||
deprecated="not deprecated"
|
||||
visibility="public"
|
||||
>
|
||||
<parameter name="view" type="android.view.View">
|
||||
</parameter>
|
||||
</method>
|
||||
<method name="updateViewLayout"
|
||||
return="void"
|
||||
abstract="false"
|
||||
|
||||
@@ -686,6 +686,13 @@ public class ValueAnimator<T> extends Animator {
|
||||
private void start(boolean playBackwards) {
|
||||
mPlayingBackwards = playBackwards;
|
||||
if ((mStartDelay == 0) && (Thread.currentThread() == Looper.getMainLooper().getThread())) {
|
||||
if (mListeners != null) {
|
||||
ArrayList<AnimatorListener> tmpListeners =
|
||||
(ArrayList<AnimatorListener>) mListeners.clone();
|
||||
for (AnimatorListener listener : tmpListeners) {
|
||||
listener.onAnimationStart(this);
|
||||
}
|
||||
}
|
||||
// This sets the initial value of the animation, prior to actually starting it running
|
||||
setCurrentPlayTime(getCurrentPlayTime());
|
||||
}
|
||||
@@ -783,7 +790,9 @@ public class ValueAnimator<T> extends Animator {
|
||||
private void startAnimation() {
|
||||
initAnimation();
|
||||
sAnimations.add(this);
|
||||
if (mListeners != null) {
|
||||
if (mStartDelay > 0 && mListeners != null) {
|
||||
// Listeners were already notified in start() if startDelay is 0; this is
|
||||
// just for delayed animations
|
||||
ArrayList<AnimatorListener> tmpListeners =
|
||||
(ArrayList<AnimatorListener>) mListeners.clone();
|
||||
for (AnimatorListener listener : tmpListeners) {
|
||||
|
||||
@@ -18,8 +18,7 @@ package android.app;
|
||||
|
||||
import android.animation.Animator;
|
||||
import android.animation.AnimatorInflater;
|
||||
import android.animation.AnimatorSet;
|
||||
import android.animation.ObjectAnimator;
|
||||
import android.animation.AnimatorListenerAdapter;
|
||||
import android.content.res.TypedArray;
|
||||
import android.os.Bundle;
|
||||
import android.os.Handler;
|
||||
@@ -363,11 +362,7 @@ final class FragmentManagerImpl implements FragmentManager {
|
||||
Animator anim = loadAnimator(f, transit, true,
|
||||
transitionStyle);
|
||||
if (anim != null) {
|
||||
if (anim instanceof AnimatorSet) {
|
||||
((AnimatorSet)anim).setTarget(f.mView);
|
||||
} else if (anim instanceof ObjectAnimator) {
|
||||
((ObjectAnimator)anim).setTarget(f.mView);
|
||||
}
|
||||
anim.setTarget(f.mView);
|
||||
anim.start();
|
||||
}
|
||||
container.addView(f.mView);
|
||||
@@ -447,17 +442,24 @@ final class FragmentManagerImpl implements FragmentManager {
|
||||
+ " did not call through to super.onDestroyedView()");
|
||||
}
|
||||
if (f.mView != null && f.mContainer != null) {
|
||||
Animator anim = null;
|
||||
if (mCurState > Fragment.INITIALIZING) {
|
||||
Animator anim = loadAnimator(f, transit, true,
|
||||
anim = loadAnimator(f, transit, false,
|
||||
transitionStyle);
|
||||
if (anim != null) {
|
||||
if (anim instanceof AnimatorSet) {
|
||||
((AnimatorSet)anim).setTarget(f.mView);
|
||||
} else if (anim instanceof ObjectAnimator) {
|
||||
((ObjectAnimator)anim).setTarget(f.mView);
|
||||
}
|
||||
if (anim != null) {
|
||||
final ViewGroup container = f.mContainer;
|
||||
final View view = f.mView;
|
||||
container.startViewTransition(view);
|
||||
anim.addListener(new AnimatorListenerAdapter() {
|
||||
@Override
|
||||
public void onAnimationEnd(Animator anim) {
|
||||
container.endViewTransition(view);
|
||||
}
|
||||
anim.start();
|
||||
}
|
||||
});
|
||||
anim.setTarget(f.mView);
|
||||
anim.start();
|
||||
|
||||
}
|
||||
f.mContainer.removeView(f.mView);
|
||||
}
|
||||
@@ -591,11 +593,7 @@ final class FragmentManagerImpl implements FragmentManager {
|
||||
Animator anim = loadAnimator(fragment, transition, true,
|
||||
transitionStyle);
|
||||
if (anim != null) {
|
||||
if (anim instanceof AnimatorSet) {
|
||||
((AnimatorSet)anim).setTarget(fragment.mView);
|
||||
} else if (anim instanceof ObjectAnimator) {
|
||||
((ObjectAnimator)anim).setTarget(fragment.mView);
|
||||
}
|
||||
anim.setTarget(fragment.mView);
|
||||
anim.start();
|
||||
}
|
||||
fragment.mView.setVisibility(View.GONE);
|
||||
@@ -615,11 +613,7 @@ final class FragmentManagerImpl implements FragmentManager {
|
||||
Animator anim = loadAnimator(fragment, transition, true,
|
||||
transitionStyle);
|
||||
if (anim != null) {
|
||||
if (anim instanceof AnimatorSet) {
|
||||
((AnimatorSet)anim).setTarget(fragment.mView);
|
||||
} else if (anim instanceof ObjectAnimator) {
|
||||
((ObjectAnimator)anim).setTarget(fragment.mView);
|
||||
}
|
||||
anim.setTarget(fragment.mView);
|
||||
anim.start();
|
||||
}
|
||||
fragment.mView.setVisibility(View.VISIBLE);
|
||||
|
||||
@@ -2603,6 +2603,9 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager
|
||||
* @attr ref android.R.styleable#ViewGroup_animateLayoutChanges
|
||||
*/
|
||||
public void setLayoutTransition(LayoutTransition transition) {
|
||||
if (mTransition != null) {
|
||||
mTransition.removeTransitionListener(mLayoutTransitionListener);
|
||||
}
|
||||
mTransition = transition;
|
||||
if (mTransition != null) {
|
||||
mTransition.addTransitionListener(mLayoutTransitionListener);
|
||||
@@ -3731,6 +3734,54 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This method tells the ViewGroup that the given View object, which should have this
|
||||
* ViewGroup as its parent,
|
||||
* should be kept around (re-displayed when the ViewGroup draws its children) even if it
|
||||
* is removed from its parent. This allows animations, such as those used by
|
||||
* {@link android.app.Fragment} and {@link android.animation.LayoutTransition} to animate
|
||||
* the removal of views. A call to this method should always be accompanied by a later call
|
||||
* to {@link #endViewTransition(View)}, such as after an animation on the View has finished,
|
||||
* so that the View finally gets removed.
|
||||
*
|
||||
* @param view The View object to be kept visible even if it gets removed from its parent.
|
||||
*/
|
||||
public void startViewTransition(View view) {
|
||||
if (view.mParent == this) {
|
||||
if (mTransitioningViews == null) {
|
||||
mTransitioningViews = new ArrayList<View>();
|
||||
}
|
||||
mTransitioningViews.add(view);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This method should always be called following an earlier call to
|
||||
* {@link #startViewTransition(View)}. The given View is finally removed from its parent
|
||||
* and will no longer be displayed. Note that this method does not perform the functionality
|
||||
* of removing a view from its parent; it just discontinues the display of a View that
|
||||
* has previously been removed.
|
||||
*
|
||||
* @return view The View object that has been removed but is being kept around in the visible
|
||||
* hierarchy by an earlier call to {@link #startViewTransition(View)}.
|
||||
*/
|
||||
public void endViewTransition(View view) {
|
||||
if (mTransitioningViews != null) {
|
||||
mTransitioningViews.remove(view);
|
||||
final ArrayList<View> disappearingChildren = mDisappearingChildren;
|
||||
if (disappearingChildren != null && disappearingChildren.contains(view)) {
|
||||
disappearingChildren.remove(view);
|
||||
if (view.mAttachInfo != null) {
|
||||
view.dispatchDetachedFromWindow();
|
||||
}
|
||||
if (view.mParent != null) {
|
||||
view.mParent = null;
|
||||
}
|
||||
mGroupFlags |= FLAG_INVALIDATE_REQUIRED;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private LayoutTransition.TransitionListener mLayoutTransitionListener =
|
||||
new LayoutTransition.TransitionListener() {
|
||||
@Override
|
||||
@@ -3739,10 +3790,7 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager
|
||||
// We only care about disappearing items, since we need special logic to keep
|
||||
// those items visible after they've been 'removed'
|
||||
if (transitionType == LayoutTransition.DISAPPEARING) {
|
||||
if (mTransitioningViews == null) {
|
||||
mTransitioningViews = new ArrayList<View>();
|
||||
}
|
||||
mTransitioningViews.add(view);
|
||||
startViewTransition(view);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3750,18 +3798,7 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager
|
||||
public void endTransition(LayoutTransition transition, ViewGroup container,
|
||||
View view, int transitionType) {
|
||||
if (transitionType == LayoutTransition.DISAPPEARING && mTransitioningViews != null) {
|
||||
mTransitioningViews.remove(view);
|
||||
final ArrayList<View> disappearingChildren = mDisappearingChildren;
|
||||
if (disappearingChildren != null && disappearingChildren.contains(view)) {
|
||||
disappearingChildren.remove(view);
|
||||
if (view.mAttachInfo != null) {
|
||||
view.dispatchDetachedFromWindow();
|
||||
}
|
||||
if (view.mParent != null) {
|
||||
view.mParent = null;
|
||||
}
|
||||
mGroupFlags |= FLAG_INVALIDATE_REQUIRED;
|
||||
}
|
||||
endViewTransition(view);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user