1/* 2 * Copyright (C) 2016 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 17package android.transition; 18 19import android.animation.AnimatorSetActivity; 20import android.app.Activity; 21import android.test.ActivityInstrumentationTestCase2; 22import android.test.suitebuilder.annotation.SmallTest; 23import android.view.Gravity; 24import android.view.View; 25import android.view.ViewGroup; 26import android.view.ViewTreeObserver; 27 28import com.android.frameworks.coretests.R; 29 30import java.util.concurrent.CountDownLatch; 31import java.util.concurrent.TimeUnit; 32 33 34public class SlideTransitionTest extends ActivityInstrumentationTestCase2<AnimatorSetActivity> { 35 36 Activity mActivity; 37 38 public SlideTransitionTest() { 39 super(AnimatorSetActivity.class); 40 } 41 42 @Override 43 protected void setUp() throws Exception { 44 mActivity = getActivity(); 45 } 46 47 @SmallTest 48 public void testShortSlide() throws Throwable { 49 final float slideFraction = 0.5f; 50 final View square1 = mActivity.findViewById(R.id.square1); 51 final View sceneRoot = mActivity.findViewById(R.id.container); 52 final SlideTranslationValueRatchet ratchet = new SlideTranslationValueRatchet(square1); 53 square1.getViewTreeObserver().addOnPreDrawListener(ratchet); 54 55 final Slide slideOut = new Slide(Gravity.BOTTOM); 56 final float finalOffsetOut = sceneRoot.getHeight() * slideFraction; 57 slideOut.setSlideFraction(slideFraction); 58 TransitionLatch latch = setVisibilityInTransition(slideOut, R.id.square1, View.INVISIBLE); 59 assertTrue(latch.startLatch.await(200, TimeUnit.MILLISECONDS)); 60 assertEquals(0f, square1.getTranslationY(), 0.1f); 61 assertEquals(View.VISIBLE, square1.getVisibility()); 62 Thread.sleep(100); 63 assertFalse(square1.getTranslationY() < 0.1 64 || square1.getTranslationY() > finalOffsetOut - 0.1); 65 assertTrue(latch.endLatch.await(400, TimeUnit.MILLISECONDS)); 66 // Give this 20% slop in case some frames get dropped. 67 assertTrue(finalOffsetOut * 0.8 < ratchet.maxY); 68 assertTrue(finalOffsetOut + 0.1 > ratchet.maxY); 69 assertEquals(View.INVISIBLE, square1.getVisibility()); 70 71 ratchet.reset(); 72 final Slide slideIn = new Slide(Gravity.BOTTOM); 73 final float initialOffsetIn = sceneRoot.getHeight() * slideFraction; 74 slideIn.setSlideFraction(slideFraction); 75 latch = setVisibilityInTransition(slideIn, R.id.square1, View.VISIBLE); 76 assertTrue(latch.startLatch.await(200, TimeUnit.MILLISECONDS)); 77 assertEquals(initialOffsetIn, square1.getTranslationY(), 0.1f); 78 assertEquals(View.VISIBLE, square1.getVisibility()); 79 Thread.sleep(100); 80 assertFalse(square1.getTranslationY() < 0.1 81 || square1.getTranslationY() > initialOffsetIn - 0.1); 82 assertTrue(latch.endLatch.await(400, TimeUnit.MILLISECONDS)); 83 assertEquals(0f, ratchet.minY, 0.1); 84 assertEquals(0f, square1.getTranslationY(), 0.1); 85 assertEquals(View.VISIBLE, square1.getVisibility()); 86 87 square1.getViewTreeObserver().removeOnPreDrawListener(ratchet); 88 } 89 90 public TransitionLatch setVisibilityInTransition(final Transition transition, int viewId, 91 final int visibility) throws Throwable { 92 final ViewGroup sceneRoot = (ViewGroup) mActivity.findViewById(R.id.container); 93 final View view = sceneRoot.findViewById(viewId); 94 TransitionLatch latch = new TransitionLatch(); 95 transition.addListener(latch); 96 runTestOnUiThread(new Runnable() { 97 @Override 98 public void run() { 99 TransitionManager.beginDelayedTransition(sceneRoot, transition); 100 view.setVisibility(visibility); 101 } 102 }); 103 return latch; 104 } 105 106 public static class TransitionLatch implements Transition.TransitionListener { 107 public CountDownLatch startLatch = new CountDownLatch(1); 108 public CountDownLatch endLatch = new CountDownLatch(1); 109 public CountDownLatch cancelLatch = new CountDownLatch(1); 110 public CountDownLatch pauseLatch = new CountDownLatch(1); 111 public CountDownLatch resumeLatch = new CountDownLatch(1); 112 113 @Override 114 public void onTransitionStart(Transition transition) { 115 startLatch.countDown(); 116 } 117 118 @Override 119 public void onTransitionEnd(Transition transition) { 120 endLatch.countDown(); 121 transition.removeListener(this); 122 } 123 124 @Override 125 public void onTransitionCancel(Transition transition) { 126 cancelLatch.countDown(); 127 } 128 129 @Override 130 public void onTransitionPause(Transition transition) { 131 pauseLatch.countDown(); 132 } 133 134 @Override 135 public void onTransitionResume(Transition transition) { 136 resumeLatch.countDown(); 137 } 138 } 139 140 private static class SlideTranslationValueRatchet 141 implements ViewTreeObserver.OnPreDrawListener { 142 143 private final View mView; 144 private boolean mInitialized; 145 public float minX = Float.NaN; 146 public float minY = Float.NaN; 147 public float maxX = Float.NaN; 148 public float maxY = Float.NaN; 149 150 public SlideTranslationValueRatchet(View view) { 151 mView = view; 152 } 153 154 public void reset() { 155 minX = minY = maxX = maxY = Float.NaN; 156 mInitialized = false; 157 } 158 159 @Override 160 public boolean onPreDraw() { 161 if (!mInitialized) { 162 minX = maxX = mView.getTranslationX(); 163 minY = maxY = mView.getTranslationY(); 164 mInitialized = true; 165 } else { 166 minX = Math.min(minX, mView.getTranslationX()); 167 minY = Math.min(minY, mView.getTranslationY()); 168 maxX = Math.max(maxX, mView.getTranslationX()); 169 maxY = Math.max(maxY, mView.getTranslationY()); 170 } 171 return true; 172 } 173 } 174} 175