Home | History | Annotate | Download | only in transition
      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 
     17 package android.transition;
     18 
     19 import android.animation.AnimatorSetActivity;
     20 import android.app.Activity;
     21 import android.test.ActivityInstrumentationTestCase2;
     22 import android.test.suitebuilder.annotation.SmallTest;
     23 import android.view.Gravity;
     24 import android.view.View;
     25 import android.view.ViewGroup;
     26 import android.view.ViewTreeObserver;
     27 
     28 import com.android.frameworks.coretests.R;
     29 
     30 import java.util.concurrent.CountDownLatch;
     31 import java.util.concurrent.TimeUnit;
     32 
     33 
     34 public 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