Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit ad43160b authored by Tony Mantler's avatar Tony Mantler Committed by Android (Google) Code Review
Browse files

Merge "Add hidden slide fraction call to Slide" into nyc-dev

parents ae0da24c cfa15bd1
Loading
Loading
Loading
Loading
+28 −22
Original line number Diff line number Diff line
@@ -47,6 +47,7 @@ public class Slide extends Visibility {
    private static final String PROPNAME_SCREEN_POSITION = "android:slide:screenPosition";
    private CalculateSlide mSlideCalculator = sCalculateBottom;
    private @GravityFlag int mSlideEdge = Gravity.BOTTOM;
    private float mSlideFraction = 1;

    /** @hide */
    @Retention(RetentionPolicy.SOURCE)
@@ -56,16 +57,16 @@ public class Slide extends Visibility {
    private interface CalculateSlide {

        /** Returns the translation value for view when it goes out of the scene */
        float getGoneX(ViewGroup sceneRoot, View view);
        float getGoneX(ViewGroup sceneRoot, View view, float fraction);

        /** Returns the translation value for view when it goes out of the scene */
        float getGoneY(ViewGroup sceneRoot, View view);
        float getGoneY(ViewGroup sceneRoot, View view, float fraction);
    }

    private static abstract class CalculateSlideHorizontal implements CalculateSlide {

        @Override
        public float getGoneY(ViewGroup sceneRoot, View view) {
        public float getGoneY(ViewGroup sceneRoot, View view, float fraction) {
            return view.getTranslationY();
        }
    }
@@ -73,27 +74,27 @@ public class Slide extends Visibility {
    private static abstract class CalculateSlideVertical implements CalculateSlide {

        @Override
        public float getGoneX(ViewGroup sceneRoot, View view) {
        public float getGoneX(ViewGroup sceneRoot, View view, float fraction) {
            return view.getTranslationX();
        }
    }

    private static final CalculateSlide sCalculateLeft = new CalculateSlideHorizontal() {
        @Override
        public float getGoneX(ViewGroup sceneRoot, View view) {
            return view.getTranslationX() - sceneRoot.getWidth();
        public float getGoneX(ViewGroup sceneRoot, View view, float fraction) {
            return view.getTranslationX() - sceneRoot.getWidth() * fraction;
        }
    };

    private static final CalculateSlide sCalculateStart = new CalculateSlideHorizontal() {
        @Override
        public float getGoneX(ViewGroup sceneRoot, View view) {
        public float getGoneX(ViewGroup sceneRoot, View view, float fraction) {
            final boolean isRtl = sceneRoot.getLayoutDirection() == View.LAYOUT_DIRECTION_RTL;
            final float x;
            if (isRtl) {
                x = view.getTranslationX() + sceneRoot.getWidth();
                x = view.getTranslationX() + sceneRoot.getWidth() * fraction;
            } else {
                x = view.getTranslationX() - sceneRoot.getWidth();
                x = view.getTranslationX() - sceneRoot.getWidth() * fraction;
            }
            return x;
        }
@@ -101,27 +102,27 @@ public class Slide extends Visibility {

    private static final CalculateSlide sCalculateTop = new CalculateSlideVertical() {
        @Override
        public float getGoneY(ViewGroup sceneRoot, View view) {
            return view.getTranslationY() - sceneRoot.getHeight();
        public float getGoneY(ViewGroup sceneRoot, View view, float fraction) {
            return view.getTranslationY() - sceneRoot.getHeight() * fraction;
        }
    };

    private static final CalculateSlide sCalculateRight = new CalculateSlideHorizontal() {
        @Override
        public float getGoneX(ViewGroup sceneRoot, View view) {
            return view.getTranslationX() + sceneRoot.getWidth();
        public float getGoneX(ViewGroup sceneRoot, View view, float fraction) {
            return view.getTranslationX() + sceneRoot.getWidth() * fraction;
        }
    };

    private static final CalculateSlide sCalculateEnd = new CalculateSlideHorizontal() {
        @Override
        public float getGoneX(ViewGroup sceneRoot, View view) {
        public float getGoneX(ViewGroup sceneRoot, View view, float fraction) {
            final boolean isRtl = sceneRoot.getLayoutDirection() == View.LAYOUT_DIRECTION_RTL;
            final float x;
            if (isRtl) {
                x = view.getTranslationX() - sceneRoot.getWidth();
                x = view.getTranslationX() - sceneRoot.getWidth() * fraction;
            } else {
                x = view.getTranslationX() + sceneRoot.getWidth();
                x = view.getTranslationX() + sceneRoot.getWidth() * fraction;
            }
            return x;
        }
@@ -129,8 +130,8 @@ public class Slide extends Visibility {

    private static final CalculateSlide sCalculateBottom = new CalculateSlideVertical() {
        @Override
        public float getGoneY(ViewGroup sceneRoot, View view) {
            return view.getTranslationY() + sceneRoot.getHeight();
        public float getGoneY(ViewGroup sceneRoot, View view, float fraction) {
            return view.getTranslationY() + sceneRoot.getHeight() * fraction;
        }
    };

@@ -237,8 +238,8 @@ public class Slide extends Visibility {
        int[] position = (int[]) endValues.values.get(PROPNAME_SCREEN_POSITION);
        float endX = view.getTranslationX();
        float endY = view.getTranslationY();
        float startX = mSlideCalculator.getGoneX(sceneRoot, view);
        float startY = mSlideCalculator.getGoneY(sceneRoot, view);
        float startX = mSlideCalculator.getGoneX(sceneRoot, view, mSlideFraction);
        float startY = mSlideCalculator.getGoneY(sceneRoot, view, mSlideFraction);
        return TranslationAnimationCreator
                .createAnimation(view, endValues, position[0], position[1],
                        startX, startY, endX, endY, sDecelerate, this);
@@ -253,10 +254,15 @@ public class Slide extends Visibility {
        int[] position = (int[]) startValues.values.get(PROPNAME_SCREEN_POSITION);
        float startX = view.getTranslationX();
        float startY = view.getTranslationY();
        float endX = mSlideCalculator.getGoneX(sceneRoot, view);
        float endY = mSlideCalculator.getGoneY(sceneRoot, view);
        float endX = mSlideCalculator.getGoneX(sceneRoot, view, mSlideFraction);
        float endY = mSlideCalculator.getGoneY(sceneRoot, view, mSlideFraction);
        return TranslationAnimationCreator
                .createAnimation(view, startValues, position[0], position[1],
                        startX, startY, endX, endY, sAccelerate, this);
    }

    /** @hide */
    public void setSlideFraction(float slideFraction) {
        mSlideFraction = slideFraction;
    }
}
+174 −0
Original line number Diff line number Diff line
/*
 * 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.view.Gravity;
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewTreeObserver;

import com.android.frameworks.coretests.R;

import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;


public class SlideTransitionTest extends ActivityInstrumentationTestCase2<AnimatorSetActivity> {

    Activity mActivity;

    public SlideTransitionTest() {
        super(AnimatorSetActivity.class);
    }

    @Override
    protected void setUp() throws Exception {
        mActivity = getActivity();
    }

    @SmallTest
    public void testShortSlide() throws Throwable {
        final float slideFraction = 0.5f;
        final View square1 = mActivity.findViewById(R.id.square1);
        final View sceneRoot = mActivity.findViewById(R.id.container);
        final SlideTranslationValueRatchet ratchet = new SlideTranslationValueRatchet(square1);
        square1.getViewTreeObserver().addOnPreDrawListener(ratchet);

        final Slide slideOut = new Slide(Gravity.BOTTOM);
        final float finalOffsetOut = sceneRoot.getHeight() * slideFraction;
        slideOut.setSlideFraction(slideFraction);
        TransitionLatch latch = setVisibilityInTransition(slideOut, R.id.square1, View.INVISIBLE);
        assertTrue(latch.startLatch.await(200, TimeUnit.MILLISECONDS));
        assertEquals(0f, square1.getTranslationY(), 0.1f);
        assertEquals(View.VISIBLE, square1.getVisibility());
        Thread.sleep(100);
        assertFalse(square1.getTranslationY() < 0.1
                || square1.getTranslationY() > finalOffsetOut - 0.1);
        assertTrue(latch.endLatch.await(400, TimeUnit.MILLISECONDS));
        // Give this 20% slop in case some frames get dropped.
        assertTrue(finalOffsetOut * 0.8 < ratchet.maxY);
        assertTrue(finalOffsetOut + 0.1 > ratchet.maxY);
        assertEquals(View.INVISIBLE, square1.getVisibility());

        ratchet.reset();
        final Slide slideIn = new Slide(Gravity.BOTTOM);
        final float initialOffsetIn = sceneRoot.getHeight() * slideFraction;
        slideIn.setSlideFraction(slideFraction);
        latch = setVisibilityInTransition(slideIn, R.id.square1, View.VISIBLE);
        assertTrue(latch.startLatch.await(200, TimeUnit.MILLISECONDS));
        assertEquals(initialOffsetIn, square1.getTranslationY(), 0.1f);
        assertEquals(View.VISIBLE, square1.getVisibility());
        Thread.sleep(100);
        assertFalse(square1.getTranslationY() < 0.1
                || square1.getTranslationY() > initialOffsetIn - 0.1);
        assertTrue(latch.endLatch.await(400, TimeUnit.MILLISECONDS));
        assertEquals(0f, ratchet.minY, 0.1);
        assertEquals(0f, square1.getTranslationY(), 0.1);
        assertEquals(View.VISIBLE, square1.getVisibility());

        square1.getViewTreeObserver().removeOnPreDrawListener(ratchet);
    }

    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 Transition.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 SlideTranslationValueRatchet
            implements ViewTreeObserver.OnPreDrawListener {

        private final View mView;
        private boolean mInitialized;
        public float minX = Float.NaN;
        public float minY = Float.NaN;
        public float maxX = Float.NaN;
        public float maxY = Float.NaN;

        public SlideTranslationValueRatchet(View view) {
            mView = view;
        }

        public void reset() {
            minX = minY = maxX = maxY = Float.NaN;
            mInitialized = false;
        }

        @Override
        public boolean onPreDraw() {
            if (!mInitialized) {
                minX = maxX = mView.getTranslationX();
                minY = maxY = mView.getTranslationY();
                mInitialized = true;
            } else {
                minX = Math.min(minX, mView.getTranslationX());
                minY = Math.min(minY, mView.getTranslationY());
                maxX = Math.max(maxX, mView.getTranslationX());
                maxY = Math.max(maxY, mView.getTranslationY());
            }
            return true;
        }
    }
}