diff options
| author | 2016-02-04 15:24:30 -0800 | |
|---|---|---|
| committer | 2016-02-08 20:33:49 +0000 | |
| commit | 5affef077316e73337eb42a098a126b01d20568e (patch) | |
| tree | 8c936e29aa7ccd7531a4566ce00ca269d0b3da5d | |
| parent | 95728a5db6595e473acf8f428f238afc2fdbbe80 (diff) | |
Fix Fade transition interrupt.
Bug 26963113
When a Fade transition is interrupted and reversed, the
View started the animation from the beginning. This change
captures the previous transitionAlpha and starts the animation
from the previous alpha state.
Change-Id: I801fe9ade6af4cf8446838e231bdc71841668a18
(cherry picked from commit 3cf9fa3db0231d035142c27992818d8f7827ac3e)
| -rw-r--r-- | core/java/android/transition/Fade.java | 37 | ||||
| -rw-r--r-- | core/tests/coretests/res/layout/animator_set_squares.xml | 3 | ||||
| -rw-r--r-- | core/tests/coretests/src/android/transition/FadeTransitionTest.java | 200 |
3 files changed, 223 insertions, 17 deletions
diff --git a/core/java/android/transition/Fade.java b/core/java/android/transition/Fade.java index 287c69608b8b..b2e8d3351028 100644 --- a/core/java/android/transition/Fade.java +++ b/core/java/android/transition/Fade.java @@ -57,9 +57,9 @@ import android.view.ViewGroup; * tag <code>fade</code>, along with the standard * attributes of {@link android.R.styleable#Fade} and * {@link android.R.styleable#Transition}.</p> - */ public class Fade extends Visibility { + static final String PROPNAME_TRANSITION_ALPHA = "android:fade:transitionAlpha"; private static boolean DBG = Transition.DBG && false; @@ -105,6 +105,13 @@ public class Fade extends Visibility { setMode(fadingMode); } + @Override + public void captureStartValues(TransitionValues transitionValues) { + super.captureStartValues(transitionValues); + transitionValues.values.put(PROPNAME_TRANSITION_ALPHA, + transitionValues.view.getTransitionAlpha()); + } + /** * Utility method to handle creating and running the Animator. */ @@ -119,7 +126,6 @@ public class Fade extends Visibility { } final FadeAnimatorListener listener = new FadeAnimatorListener(view); anim.addListener(listener); - anim.addPauseListener(listener); addListener(new TransitionListenerAdapter() { @Override public void onTransitionEnd(Transition transition) { @@ -138,18 +144,28 @@ public class Fade extends Visibility { Log.d(LOG_TAG, "Fade.onAppear: startView, startVis, endView, endVis = " + startView + ", " + view); } - return createAnimation(view, 0, 1); + float startAlpha = 0; + if (startValues != null) { + startAlpha = (Float) startValues.values.get(PROPNAME_TRANSITION_ALPHA); + if (startAlpha == 1) { + startAlpha = 0; + } + } + return createAnimation(view, startAlpha, 1); } @Override public Animator onDisappear(ViewGroup sceneRoot, final View view, TransitionValues startValues, TransitionValues endValues) { - return createAnimation(view, 1, 0); + float startAlpha = 1; + if (startValues != null) { + startAlpha = (Float) startValues.values.get(PROPNAME_TRANSITION_ALPHA); + } + return createAnimation(view, startAlpha, 0); } private static class FadeAnimatorListener extends AnimatorListenerAdapter { private final View mView; - private float mPausedAlpha = -1; private boolean mLayerTypeChanged = false; public FadeAnimatorListener(View view) { @@ -171,16 +187,5 @@ public class Fade extends Visibility { mView.setLayerType(View.LAYER_TYPE_NONE, null); } } - - @Override - public void onAnimationPause(Animator animator) { - mPausedAlpha = mView.getTransitionAlpha(); - mView.setTransitionAlpha(1); - } - - @Override - public void onAnimationResume(Animator animator) { - mView.setTransitionAlpha(mPausedAlpha); - } } } diff --git a/core/tests/coretests/res/layout/animator_set_squares.xml b/core/tests/coretests/res/layout/animator_set_squares.xml index 23e6eea06a2b..6888248f5b13 100644 --- a/core/tests/coretests/res/layout/animator_set_squares.xml +++ b/core/tests/coretests/res/layout/animator_set_squares.xml @@ -4,7 +4,8 @@ android:layout_width="fill_parent" android:layout_height="fill_parent" android:background="@android:color/white" - android:orientation="horizontal"> + android:orientation="horizontal" + android:id="@+id/container"> <View android:layout_width="50dp" android:layout_height="50dp" diff --git a/core/tests/coretests/src/android/transition/FadeTransitionTest.java b/core/tests/coretests/src/android/transition/FadeTransitionTest.java new file mode 100644 index 000000000000..dc6042311095 --- /dev/null +++ b/core/tests/coretests/src/android/transition/FadeTransitionTest.java @@ -0,0 +1,200 @@ +/* + * Copyright (C) 2016 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.transition; + +import android.animation.AnimatorSetActivity; +import android.app.Activity; +import android.test.ActivityInstrumentationTestCase2; +import android.test.suitebuilder.annotation.SmallTest; +import android.transition.Transition.TransitionListener; +import android.transition.Transition.TransitionListenerAdapter; +import android.view.View; +import android.view.ViewGroup; + +import com.android.frameworks.coretests.R; + +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.TimeUnit; + +import static android.support.test.espresso.Espresso.onView; + +public class FadeTransitionTest extends ActivityInstrumentationTestCase2<AnimatorSetActivity> { + Activity mActivity; + public FadeTransitionTest() { + super(AnimatorSetActivity.class); + } + + @Override + protected void setUp() throws Exception { + mActivity = getActivity(); + } + + @SmallTest + public void testFadeOutAndIn() throws Throwable { + View square1 = mActivity.findViewById(R.id.square1); + Fade fadeOut = new Fade(Fade.MODE_OUT); + TransitionLatch latch = setVisibilityInTransition(fadeOut, R.id.square1, View.INVISIBLE); + assertTrue(latch.startLatch.await(200, TimeUnit.MILLISECONDS)); + assertEquals(View.VISIBLE, square1.getVisibility()); + Thread.sleep(100); + assertFalse(square1.getTransitionAlpha() == 0 || square1.getTransitionAlpha() == 1); + assertTrue(latch.endLatch.await(400, TimeUnit.MILLISECONDS)); + assertEquals(1.0f, square1.getTransitionAlpha()); + assertEquals(View.INVISIBLE, square1.getVisibility()); + + Fade fadeIn = new Fade(Fade.MODE_IN); + latch = setVisibilityInTransition(fadeIn, R.id.square1, View.VISIBLE); + assertTrue(latch.startLatch.await(200, TimeUnit.MILLISECONDS)); + assertEquals(View.VISIBLE, square1.getVisibility()); + Thread.sleep(100); + final float transitionAlpha = square1.getTransitionAlpha(); + assertTrue("expecting transitionAlpha to be between 0 and 1. Was " + transitionAlpha, + transitionAlpha > 0 && transitionAlpha < 1); + assertTrue(latch.endLatch.await(400, TimeUnit.MILLISECONDS)); + assertEquals(1.0f, square1.getTransitionAlpha()); + assertEquals(View.VISIBLE, square1.getVisibility()); + } + + @SmallTest + public void testFadeOutInterrupt() throws Throwable { + View square1 = mActivity.findViewById(R.id.square1); + Fade fadeOut = new Fade(Fade.MODE_OUT); + FadeValueCheck fadeOutValueCheck = new FadeValueCheck(square1); + fadeOut.addListener(fadeOutValueCheck); + TransitionLatch outLatch = setVisibilityInTransition(fadeOut, R.id.square1, View.INVISIBLE); + assertTrue(outLatch.startLatch.await(200, TimeUnit.MILLISECONDS)); + Thread.sleep(100); + + Fade fadeIn = new Fade(Fade.MODE_IN); + FadeValueCheck fadeInValueCheck = new FadeValueCheck(square1); + fadeIn.addListener(fadeInValueCheck); + TransitionLatch inLatch = setVisibilityInTransition(fadeIn, R.id.square1, View.VISIBLE); + assertTrue(inLatch.startLatch.await(200, TimeUnit.MILLISECONDS)); + + assertEquals(fadeOutValueCheck.pauseTransitionAlpha, fadeInValueCheck.startTransitionAlpha); + assertTrue("expecting transitionAlpha to be between 0 and 1. Was " + + fadeOutValueCheck.pauseTransitionAlpha, + fadeOutValueCheck.pauseTransitionAlpha > 0 && + fadeOutValueCheck.pauseTransitionAlpha < 1); + + assertTrue(inLatch.endLatch.await(400, TimeUnit.MILLISECONDS)); + assertEquals(1.0f, square1.getTransitionAlpha()); + assertEquals(View.VISIBLE, square1.getVisibility()); + } + + @SmallTest + public void testFadeInInterrupt() throws Throwable { + final View square1 = mActivity.findViewById(R.id.square1); + runTestOnUiThread(new Runnable() { + @Override + public void run() { + square1.setVisibility(View.INVISIBLE); + } + }); + Fade fadeIn = new Fade(Fade.MODE_IN); + FadeValueCheck fadeInValueCheck = new FadeValueCheck(square1); + fadeIn.addListener(fadeInValueCheck); + TransitionLatch inLatch = setVisibilityInTransition(fadeIn, R.id.square1, View.VISIBLE); + assertTrue(inLatch.startLatch.await(200, TimeUnit.MILLISECONDS)); + Thread.sleep(100); + + Fade fadeOut = new Fade(Fade.MODE_OUT); + FadeValueCheck fadeOutValueCheck = new FadeValueCheck(square1); + fadeOut.addListener(fadeOutValueCheck); + TransitionLatch outLatch = setVisibilityInTransition(fadeOut, R.id.square1, View.INVISIBLE); + assertTrue(outLatch.startLatch.await(200, TimeUnit.MILLISECONDS)); + + assertEquals(fadeOutValueCheck.pauseTransitionAlpha, fadeInValueCheck.startTransitionAlpha); + assertTrue("expecting transitionAlpha to be between 0 and 1. Was " + + fadeInValueCheck.pauseTransitionAlpha, + fadeInValueCheck.pauseTransitionAlpha > 0 && + fadeInValueCheck.pauseTransitionAlpha < 1); + + assertTrue(outLatch.endLatch.await(400, TimeUnit.MILLISECONDS)); + assertEquals(1.0f, square1.getTransitionAlpha()); + assertEquals(View.INVISIBLE, square1.getVisibility()); + } + + public TransitionLatch setVisibilityInTransition(final Transition transition, int viewId, + final int visibility) throws Throwable { + final ViewGroup sceneRoot = (ViewGroup) mActivity.findViewById(R.id.container); + final View view = sceneRoot.findViewById(viewId); + TransitionLatch latch = new TransitionLatch(); + transition.addListener(latch); + runTestOnUiThread(new Runnable() { + @Override + public void run() { + TransitionManager.beginDelayedTransition(sceneRoot, transition); + view.setVisibility(visibility); + } + }); + return latch; + } + + public static class TransitionLatch implements TransitionListener { + public CountDownLatch startLatch = new CountDownLatch(1); + public CountDownLatch endLatch = new CountDownLatch(1); + public CountDownLatch cancelLatch = new CountDownLatch(1); + public CountDownLatch pauseLatch = new CountDownLatch(1); + public CountDownLatch resumeLatch = new CountDownLatch(1); + + @Override + public void onTransitionStart(Transition transition) { + startLatch.countDown(); + } + + @Override + public void onTransitionEnd(Transition transition) { + endLatch.countDown(); + transition.removeListener(this); + } + + @Override + public void onTransitionCancel(Transition transition) { + cancelLatch.countDown(); + } + + @Override + public void onTransitionPause(Transition transition) { + pauseLatch.countDown(); + } + + @Override + public void onTransitionResume(Transition transition) { + resumeLatch.countDown(); + } + } + + private static class FadeValueCheck extends TransitionListenerAdapter { + public float startTransitionAlpha; + public float pauseTransitionAlpha; + private final View mView; + + public FadeValueCheck(View view) { + mView = view; + } + @Override + public void onTransitionStart(Transition transition) { + startTransitionAlpha = mView.getTransitionAlpha(); + } + + @Override + public void onTransitionPause(Transition transition) { + pauseTransitionAlpha = mView.getTransitionAlpha(); + } + } +} |