• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2015 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 package android.transition.cts;
17 
18 import android.animation.Animator;
19 import android.animation.AnimatorListenerAdapter;
20 import android.graphics.Rect;
21 import android.os.Debug;
22 import android.os.SystemClock;
23 import android.transition.ArcMotion;
24 import android.transition.AutoTransition;
25 import android.transition.ChangeBounds;
26 import android.transition.PathMotion;
27 import android.transition.Scene;
28 import android.transition.Transition;
29 import android.transition.Transition.EpicenterCallback;
30 import android.transition.Transition.TransitionListener;
31 import android.transition.TransitionManager;
32 import android.transition.TransitionPropagation;
33 import android.transition.TransitionValues;
34 import android.view.View;
35 import android.view.ViewGroup;
36 import android.view.animation.AccelerateInterpolator;
37 import android.widget.ImageView;
38 import android.widget.RelativeLayout;
39 import android.widget.TextView;
40 
41 import java.util.HashMap;
42 import java.util.concurrent.CountDownLatch;
43 import java.util.concurrent.TimeUnit;
44 
45 public class TransitionTest extends BaseTransitionTest {
46 
TransitionTest()47     public TransitionTest() {
48     }
49 
testAddListener()50     public void testAddListener() throws Throwable {
51         startTransition(R.layout.scene1);
52         waitForStart();
53 
54         final SimpleTransitionListener listener2 = new SimpleTransitionListener();
55 
56         runTestOnUiThread(new Runnable() {
57             @Override
58             public void run() {
59                 AutoTransition autoTransition = new AutoTransition();
60                 autoTransition.setDuration(100);
61                 autoTransition.addListener(listener2);
62                 Scene scene = Scene.getSceneForLayout(mSceneRoot, R.layout.scene2, mActivity);
63                 TransitionManager.go(scene, autoTransition);
64             }
65         });
66 
67         waitForStart(listener2);
68 
69         assertEquals(0, mListener.pauseLatch.getCount());
70         assertEquals(0, mListener.resumeLatch.getCount());
71         assertEquals(1, mListener.cancelLatch.getCount());
72         assertEquals(1, mListener.endLatch.getCount());
73         assertEquals(0, mListener.startLatch.getCount());
74 
75         assertEquals(1, listener2.pauseLatch.getCount());
76         assertEquals(1, listener2.resumeLatch.getCount());
77         assertEquals(1, listener2.cancelLatch.getCount());
78         assertEquals(1, listener2.endLatch.getCount());
79         assertEquals(0, listener2.startLatch.getCount());
80         endTransition();
81     }
82 
testRemoveListener()83     public void testRemoveListener() throws Throwable {
84         startTransition(R.layout.scene1);
85         waitForStart();
86 
87         runTestOnUiThread(new Runnable() {
88             @Override
89             public void run() {
90                 mTransition.removeListener(mListener);
91             }
92         });
93 
94         assertFalse(mListener.endLatch.await(250, TimeUnit.MILLISECONDS));
95     }
96 
testAddTargetId()97     public void testAddTargetId() throws Throwable {
98         enterScene(R.layout.scene4);
99         assertNotNull(mTransition.getTargetIds());
100         assertTrue(mTransition.getTargetIds().isEmpty());
101         mTransition.addTarget(R.id.holder);
102         mTransition.addTarget(R.id.hello);
103         assertEquals(2, mTransition.getTargetIds().size());
104         startTransition(R.layout.scene1);
105         assertEquals(1, mTargets.size());
106         assertEquals(R.id.hello, mTargets.get(0).getId());
107         endTransition();
108     }
109 
testRemoveTargetId()110     public void testRemoveTargetId() throws Throwable {
111         enterScene(R.layout.scene4);
112         mTransition.addTarget(R.id.holder);
113         mTransition.addTarget(R.id.hello);
114         mTransition.addTarget(R.id.redSquare);
115         assertEquals(3, mTransition.getTargetIds().size());
116         mTransition.removeTarget(0); // nothing should happen
117         mTransition.removeTarget(R.id.redSquare);
118         assertEquals(2, mTransition.getTargetIds().size());
119 
120         startTransition(R.layout.scene1);
121         assertEquals(1, mTargets.size());
122         assertEquals(R.id.hello, mTargets.get(0).getId());
123         endTransition();
124     }
125 
testAddTargetClass()126     public void testAddTargetClass() throws Throwable {
127         enterScene(R.layout.scene4);
128         assertNull(mTransition.getTargetTypes());
129         mTransition.addTarget(RelativeLayout.class);
130         mTransition.addTarget(TextView.class);
131         assertEquals(2, mTransition.getTargetTypes().size());
132         startTransition(R.layout.scene1);
133         assertEquals(1, mTargets.size());
134         assertTrue(mTargets.get(0) instanceof TextView);
135         endTransition();
136     }
137 
testRemoveTargetClass()138     public void testRemoveTargetClass() throws Throwable {
139         enterScene(R.layout.scene4);
140         mTransition.addTarget(TextView.class);
141         mTransition.addTarget(View.class);
142         mTransition.addTarget(RelativeLayout.class);
143         assertEquals(3, mTransition.getTargetTypes().size());
144         mTransition.removeTarget(ImageView.class); // should do nothing
145         mTransition.removeTarget(View.class);
146         assertEquals(2, mTransition.getTargetTypes().size());
147         startTransition(R.layout.scene1);
148         assertEquals(1, mTargets.size());
149         assertTrue(mTargets.get(0) instanceof TextView);
150         endTransition();
151     }
152 
testAddTargetView()153     public void testAddTargetView() throws Throwable {
154         enterScene(R.layout.scene1);
155 
156         final View[] target = new View[1];
157         runTestOnUiThread(new Runnable() {
158             @Override
159             public void run() {
160                 target[0] = mActivity.findViewById(R.id.hello);
161             }
162         });
163         mTransition.addTarget(target[0]);
164         assertEquals(1, mTransition.getTargets().size());
165         runTestOnUiThread(new Runnable() {
166             @Override
167             public void run() {
168                 TransitionManager.beginDelayedTransition(mSceneRoot, mTransition);
169                 target[0].setVisibility(View.GONE);
170             }
171         });
172         waitForStart();
173         assertEquals(1, mTargets.size());
174         assertEquals(target[0], mTargets.get(0));
175         endTransition();
176     }
177 
testRemoveTargetView()178     public void testRemoveTargetView() throws Throwable {
179         enterScene(R.layout.scene1);
180 
181         final View[] target = new View[3];
182         runTestOnUiThread(new Runnable() {
183             @Override
184             public void run() {
185                 target[0] = mActivity.findViewById(R.id.hello);
186                 target[1] = mActivity.findViewById(R.id.greenSquare);
187                 target[2] = mActivity.findViewById(R.id.redSquare);
188             }
189         });
190 
191         mTransition.addTarget(target[0]);
192         mTransition.addTarget(target[1]);
193         assertEquals(2, mTransition.getTargets().size());
194         mTransition.removeTarget(target[2]); // should do nothing
195         mTransition.removeTarget(target[1]);
196         assertEquals(1, mTransition.getTargets().size());
197         runTestOnUiThread(new Runnable() {
198             @Override
199             public void run() {
200                 TransitionManager.beginDelayedTransition(mSceneRoot, mTransition);
201                 target[0].setVisibility(View.GONE);
202             }
203         });
204         waitForStart();
205         assertEquals(1, mTargets.size());
206         assertEquals(target[0], mTargets.get(0));
207         endTransition();
208     }
209 
testAddTargetName()210     public void testAddTargetName() throws Throwable {
211         enterScene(R.layout.scene4);
212         assertNull(mTransition.getTargetNames());
213         mTransition.addTarget("red");
214         mTransition.addTarget("holder");
215         assertEquals(2, mTransition.getTargetNames().size());
216         assertEquals(0, mTargets.size());
217         startTransition(R.layout.scene2);
218         assertEquals(1, mTargets.size());
219         assertEquals(R.id.redSquare, mTargets.get(0).getId());
220         endTransition();
221     }
222 
testRemoveTargetName()223     public void testRemoveTargetName() throws Throwable {
224         enterScene(R.layout.scene4);
225         mTransition.addTarget("holder");
226         mTransition.addTarget("red");
227         mTransition.addTarget("green");
228         assertEquals(3, mTransition.getTargetNames().size());
229         mTransition.removeTarget("purple"); // should do nothing
230         // try to force a different String instance
231         String greenName = new StringBuilder("gre").append("en").toString();
232         mTransition.removeTarget(greenName);
233         assertEquals(2, mTransition.getTargetNames().size());
234         startTransition(R.layout.scene1);
235         assertEquals(1, mTargets.size());
236         assertEquals(R.id.redSquare, mTargets.get(0).getId());
237         endTransition();
238     }
239 
testIsTransitionRequired()240     public void testIsTransitionRequired() throws Throwable {
241         enterScene(R.layout.scene1);
242         mTransition = new NotRequiredTransition();
243         resetListener();
244         runTestOnUiThread(new Runnable() {
245             @Override
246             public void run() {
247                 TransitionManager.beginDelayedTransition(mSceneRoot, mTransition);
248                 mActivity.findViewById(R.id.hello).setVisibility(View.GONE);
249             }
250         });
251         waitForStart();
252         assertEquals(0, mTargets.size());
253         endTransition();
254     }
255 
testCanRemoveViews()256     public void testCanRemoveViews() throws Throwable {
257         enterScene(R.layout.scene1);
258         assertFalse(mTransition.canRemoveViews());
259         mTransition.addListener(new TransitionListener() {
260             @Override
261             public void onTransitionStart(Transition transition) {
262                 assertTrue(transition.canRemoveViews());
263             }
264 
265             @Override
266             public void onTransitionEnd(Transition transition) {
267             }
268 
269             @Override
270             public void onTransitionCancel(Transition transition) {
271             }
272 
273             @Override
274             public void onTransitionPause(Transition transition) {
275             }
276 
277             @Override
278             public void onTransitionResume(Transition transition) {
279             }
280         });
281         startTransition(R.layout.scene2);
282     }
283 
testExcludeChildrenView()284     public void testExcludeChildrenView() throws Throwable {
285         View layout1 = loadLayout(R.layout.scene1);
286         Scene scene1 = loadScene(layout1);
287         enterScene(R.layout.scene1);
288         View holder1 = layout1.findViewById(R.id.holder);
289         mTransition.excludeChildren(holder1, true);
290         View layout2 = loadLayout(R.layout.scene2);
291         Scene scene2 = loadScene(layout2);
292         View holder2 = layout2.findViewById(R.id.holder);
293         mTransition.excludeChildren(holder2, true);
294         startTransition(scene2);
295         waitForEnd(0); // Should already be ended, since no children are transitioning
296 
297         mTransition.excludeChildren(holder1, false); // remove it
298         mTransition.excludeChildren(holder2, false); // remove it
299         resetListener();
300         startTransition(scene1);
301         assertEquals(1, mListener.endLatch.getCount()); // it is running as expected
302         endTransition();
303     }
304 
testExcludeChildrenId()305     public void testExcludeChildrenId() throws Throwable {
306         enterScene(R.layout.scene1);
307         mTransition.excludeChildren(R.id.holder, true);
308         startTransition(R.layout.scene2);
309         waitForEnd(0); // Should already be ended, since no children are transitioning
310 
311         resetListener();
312         mTransition.excludeChildren(R.id.holder, false); // remove it
313         startTransition(R.layout.scene1);
314         assertEquals(1, mListener.endLatch.getCount()); // It is running
315         endTransition();
316     }
317 
testExcludeTargetView()318     public void testExcludeTargetView() throws Throwable {
319         View layout1 = loadLayout(R.layout.scene1);
320         Scene scene1 = loadScene(layout1);
321         enterScene(R.layout.scene1);
322         View redSquare1 = layout1.findViewById(R.id.redSquare);
323         mTransition.excludeTarget(redSquare1, true);
324         startTransition(R.layout.scene7);
325         waitForEnd(0); // Should already be ended, since no children are transitioning
326 
327         mTransition.excludeTarget(redSquare1, false); // remove it
328         resetListener();
329         startTransition(scene1);
330         assertEquals(1, mListener.endLatch.getCount()); // it is running as expected
331         endTransition();
332     }
333 
testExcludeTargetId()334     public void testExcludeTargetId() throws Throwable {
335         enterScene(R.layout.scene1);
336         mTransition.excludeTarget(R.id.redSquare, true);
337         startTransition(R.layout.scene7);
338         waitForEnd(0); // Should already be ended, since no children are transitioning
339 
340         resetListener();
341         mTransition.excludeTarget(R.id.redSquare, false); // remove it
342         startTransition(R.layout.scene1);
343         assertEquals(1, mListener.endLatch.getCount()); // It is running
344         endTransition();
345     }
346 
testExcludeTargetClass()347     public void testExcludeTargetClass() throws Throwable {
348         enterScene(R.layout.scene1);
349         mTransition.excludeTarget(TextView.class, true);
350         startTransition(R.layout.scene3);
351         waitForEnd(0); // Should already be ended, since no children are transitioning
352 
353         resetListener();
354         mTransition.excludeTarget(TextView.class, false); // remove it
355         startTransition(R.layout.scene1);
356         assertEquals(1, mListener.endLatch.getCount()); // It is running
357         endTransition();
358     }
359 
testExcludeTargetName()360     public void testExcludeTargetName() throws Throwable {
361         enterScene(R.layout.scene1);
362         mTransition.excludeTarget("hello", true);
363         startTransition(R.layout.scene3);
364         waitForEnd(0); // Should already be ended, since no children are transitioning
365 
366         resetListener();
367         mTransition.excludeTarget("hello", false); // remove it
368         startTransition(R.layout.scene1);
369         assertEquals(1, mListener.endLatch.getCount()); // It is running
370         endTransition();
371     }
372 
testDuration()373     public void testDuration() throws Throwable {
374         assertEquals(-1, mTransition.getDuration());
375         enterScene(R.layout.scene1);
376         mTransition.setDuration(500);
377         assertEquals(500, mTransition.getDuration());
378         startTransition(R.layout.scene3);
379         long startTime = SystemClock.uptimeMillis();
380         waitForEnd(600);
381         long endTime = SystemClock.uptimeMillis();
382         assertEquals(500, endTime - startTime, 100);
383     }
384 
testEpicenter()385     public void testEpicenter() throws Throwable {
386         EpicenterCallback callback = new EpicenterCallback() {
387             @Override
388             public Rect onGetEpicenter(Transition transition) {
389                 return new Rect(0, 0, 1, 1);
390             }
391         };
392         mTransition.setEpicenterCallback(callback);
393         assertEquals(callback, mTransition.getEpicenterCallback());
394     }
395 
testInterpolator()396     public void testInterpolator() throws Throwable {
397         enterScene(R.layout.scene1);
398         View redSquare = mActivity.findViewById(R.id.redSquare);
399         CaptureAnimatorTransition transition = new CaptureAnimatorTransition();
400         assertNull(transition.getInterpolator());
401         AccelerateInterpolator interpolator = new AccelerateInterpolator();
402         transition.setInterpolator(interpolator);
403         assertSame(interpolator, transition.getInterpolator());
404         mTransition = transition;
405         resetListener();
406         startTransition(R.layout.scene4);
407         assertFalse(transition.animators.isEmpty());
408         Animator animator = transition.animators.get(redSquare);
409         AnimationStartListener listener = transition.listeners.get(redSquare);
410         assertTrue(listener.startLatch.await(100, TimeUnit.MILLISECONDS));
411         assertSame(interpolator, animator.getInterpolator());
412         endTransition();
413     }
414 
testName()415     public void testName() throws Throwable {
416         assertEquals("android.transition.cts.BaseTransitionTest$TestTransition",
417                 mTransition.getName());
418     }
419 
testPathMotion()420     public void testPathMotion() throws Throwable {
421         PathMotion pathMotion = new ArcMotion();
422         mTransition.setPathMotion(pathMotion);
423         assertEquals(pathMotion, mTransition.getPathMotion());
424     }
425 
testPropagation()426     public void testPropagation() throws Throwable {
427         enterScene(R.layout.scene1);
428         CaptureAnimatorTransition transition = new CaptureAnimatorTransition();
429         mTransition = transition;
430         TransitionPropagation yPropagation = new TransitionPropagation() {
431             private static final String TOP = "top value";
432             private final String[] PROPERTIES = {TOP};
433 
434             @Override
435             public long getStartDelay(ViewGroup viewGroup, Transition transition,
436                     TransitionValues startValues, TransitionValues endValues) {
437                 int startTop = startValues == null ? 0 : (Integer) startValues.values.get(TOP);
438                 int endTop = endValues == null ? 0 : (Integer) endValues.values.get(TOP);
439                 return (startTop == 0) ? endTop : startTop;
440             }
441 
442             @Override
443             public void captureValues(TransitionValues transitionValues) {
444                 if (transitionValues.view != null) {
445                     transitionValues.values.put(TOP, transitionValues.view.getTop());
446                 }
447             }
448 
449             @Override
450             public String[] getPropagationProperties() {
451                 return PROPERTIES;
452             }
453         };
454         mTransition.setPropagation(yPropagation);
455         resetListener();
456 
457         View redSquare = mActivity.findViewById(R.id.redSquare);
458         View greenSquare = mActivity.findViewById(R.id.greenSquare);
459         int diffTop = greenSquare.getTop() - redSquare.getTop();
460         startTransition(R.layout.scene4);
461         Animator redSquareAnimator = transition.animators.get(redSquare);
462         Animator greenSquareAnimator = transition.animators.get(greenSquare);
463         AnimationStartListener listener = transition.listeners.get(redSquare);
464         assertTrue(listener.startLatch.await(100, TimeUnit.MILLISECONDS));
465         assertEquals(0, redSquareAnimator.getStartDelay());
466         assertEquals(diffTop, greenSquareAnimator.getStartDelay());
467         endTransition();
468     }
469 
testStartDelay()470     public void testStartDelay() throws Throwable {
471         CaptureAnimatorTransition transition = new CaptureAnimatorTransition();
472         mTransition = transition;
473         resetListener();
474         enterScene(R.layout.scene1);
475         View redSquare = mActivity.findViewById(R.id.redSquare);
476 
477         assertEquals(-1, mTransition.getStartDelay());
478         mTransition.setStartDelay(200);
479         assertEquals(200, mTransition.getStartDelay());
480 
481         startTransition(R.layout.scene4);
482 
483         Animator animator = transition.animators.get(redSquare);
484         assertFalse(animator.isRunning());
485         AnimationStartListener listener = transition.listeners.get(redSquare);
486         assertTrue(listener.startLatch.await(250, TimeUnit.MILLISECONDS));
487         endTransition();
488     }
489 
testTransitionValues()490     public void testTransitionValues() throws Throwable {
491         enterScene(R.layout.scene1);
492         mTransition = new CheckTransitionValuesTransition();
493         mTransition.setDuration(10);
494         resetListener();
495         startTransition(R.layout.scene4);
496         // The transition has all the asserts in it, so we can just end it now.
497         endTransition();
498     }
499 
testMatchOrder()500     public void testMatchOrder() throws Throwable {
501         mTransition = new ChangeBounds();
502         resetListener();
503         enterScene(R.layout.scene1);
504         startTransition(R.layout.scene8);
505 
506         // scene 8 swaps the ids, but not the names. No transition should happen.
507         waitForEnd(0);
508 
509         // now change the match order to prefer the id
510         mTransition.setMatchOrder(new int[] {Transition.MATCH_ID, Transition.MATCH_NAME});
511 
512         resetListener();
513         startTransition(R.layout.scene1);
514         assertEquals(1, mListener.endLatch.getCount());
515         waitForEnd(400);
516     }
517 
518     private class NotRequiredTransition extends TestTransition {
519         @Override
isTransitionRequired(TransitionValues startValues, TransitionValues newValues)520         public boolean isTransitionRequired(TransitionValues startValues,
521                 TransitionValues newValues) {
522             return false;
523         }
524     }
525 
526     private class CaptureAnimatorTransition extends TestTransition {
527         public HashMap<View, Animator> animators = new HashMap<>();
528         public HashMap<View, AnimationStartListener> listeners = new HashMap<>();
529 
530         @Override
onAppear(ViewGroup sceneRoot, View view, TransitionValues startValues, TransitionValues endValues)531         public Animator onAppear(ViewGroup sceneRoot, View view, TransitionValues startValues,
532                 TransitionValues endValues) {
533             return setupAnimator(super.onAppear(sceneRoot, view, startValues, endValues),
534                     endValues.view);
535         }
536 
537         @Override
onDisappear(ViewGroup sceneRoot, View view, TransitionValues startValues, TransitionValues endValues)538         public Animator onDisappear(ViewGroup sceneRoot, View view, TransitionValues startValues,
539                 TransitionValues endValues) {
540             return setupAnimator(super.onDisappear(sceneRoot, view, startValues, endValues),
541                     startValues.view);
542         }
543 
setupAnimator(Animator animator, View view)544         private Animator setupAnimator(Animator animator, View view) {
545             animators.put(view, animator);
546             AnimationStartListener listener = new AnimationStartListener();
547             animator.addListener(listener);
548             listeners.put(view, listener);
549             return animator;
550         }
551     }
552 
553     private class CheckTransitionValuesTransition extends TestTransition {
554         @Override
onAppear(ViewGroup sceneRoot, View view, TransitionValues startValues, TransitionValues endValues)555         public Animator onAppear(ViewGroup sceneRoot, View view, TransitionValues startValues,
556                 TransitionValues endValues) {
557             assertNull(getTransitionValues(endValues.view, true));
558             assertEquals(endValues, getTransitionValues(endValues.view, false));
559             return super.onAppear(sceneRoot, view, startValues, endValues);
560         }
561 
562         @Override
onDisappear(ViewGroup sceneRoot, View view, TransitionValues startValues, TransitionValues endValues)563         public Animator onDisappear(ViewGroup sceneRoot, View view, TransitionValues startValues,
564                 TransitionValues endValues) {
565             assertNull(getTransitionValues(startValues.view, false));
566             assertEquals(startValues, getTransitionValues(startValues.view, true));
567             return super.onDisappear(sceneRoot, view, startValues, endValues);
568         }
569     }
570 
571     private class AnimationStartListener extends AnimatorListenerAdapter {
572         public CountDownLatch startLatch = new CountDownLatch(1);
573 
574         @Override
onAnimationStart(Animator animation)575         public void onAnimationStart(Animator animation) {
576             startLatch.countDown();
577         }
578     }
579 }
580 
581