AppearAnimationUtils.java revision 3018197cf0dff5a9061f6065a8ecc108a0866dab
115a77f7da856cbed19cb67c75268505a333352f1Jorim Jaggi/*
215a77f7da856cbed19cb67c75268505a333352f1Jorim Jaggi * Copyright (C) 2014 The Android Open Source Project
315a77f7da856cbed19cb67c75268505a333352f1Jorim Jaggi *
415a77f7da856cbed19cb67c75268505a333352f1Jorim Jaggi * Licensed under the Apache License, Version 2.0 (the "License");
515a77f7da856cbed19cb67c75268505a333352f1Jorim Jaggi * you may not use this file except in compliance with the License.
615a77f7da856cbed19cb67c75268505a333352f1Jorim Jaggi * You may obtain a copy of the License at
715a77f7da856cbed19cb67c75268505a333352f1Jorim Jaggi *
815a77f7da856cbed19cb67c75268505a333352f1Jorim Jaggi *      http://www.apache.org/licenses/LICENSE-2.0
915a77f7da856cbed19cb67c75268505a333352f1Jorim Jaggi *
1015a77f7da856cbed19cb67c75268505a333352f1Jorim Jaggi * Unless required by applicable law or agreed to in writing, software
1115a77f7da856cbed19cb67c75268505a333352f1Jorim Jaggi * distributed under the License is distributed on an "AS IS" BASIS,
1215a77f7da856cbed19cb67c75268505a333352f1Jorim Jaggi * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1315a77f7da856cbed19cb67c75268505a333352f1Jorim Jaggi * See the License for the specific language governing permissions and
1415a77f7da856cbed19cb67c75268505a333352f1Jorim Jaggi * limitations under the License
1515a77f7da856cbed19cb67c75268505a333352f1Jorim Jaggi */
1615a77f7da856cbed19cb67c75268505a333352f1Jorim Jaggi
1715a77f7da856cbed19cb67c75268505a333352f1Jorim Jaggipackage com.android.keyguard;
1815a77f7da856cbed19cb67c75268505a333352f1Jorim Jaggi
1915a77f7da856cbed19cb67c75268505a333352f1Jorim Jaggiimport android.content.Context;
2015a77f7da856cbed19cb67c75268505a333352f1Jorim Jaggiimport android.view.View;
2115a77f7da856cbed19cb67c75268505a333352f1Jorim Jaggiimport android.view.animation.AnimationUtils;
2215a77f7da856cbed19cb67c75268505a333352f1Jorim Jaggiimport android.view.animation.Interpolator;
2315a77f7da856cbed19cb67c75268505a333352f1Jorim Jaggi
2415a77f7da856cbed19cb67c75268505a333352f1Jorim Jaggi/**
2515a77f7da856cbed19cb67c75268505a333352f1Jorim Jaggi * A class to make nice appear transitions for views in a tabular layout.
2615a77f7da856cbed19cb67c75268505a333352f1Jorim Jaggi */
273018197cf0dff5a9061f6065a8ecc108a0866dabSelim Cinekpublic class AppearAnimationUtils implements AppearAnimationCreator<View> {
2815a77f7da856cbed19cb67c75268505a333352f1Jorim Jaggi
2915a77f7da856cbed19cb67c75268505a333352f1Jorim Jaggi    public static final long APPEAR_DURATION = 220;
3015a77f7da856cbed19cb67c75268505a333352f1Jorim Jaggi
3115a77f7da856cbed19cb67c75268505a333352f1Jorim Jaggi    private final Interpolator mLinearOutSlowIn;
3215a77f7da856cbed19cb67c75268505a333352f1Jorim Jaggi    private final float mStartTranslation;
333018197cf0dff5a9061f6065a8ecc108a0866dabSelim Cinek    private final AppearAnimationProperties mProperties = new AppearAnimationProperties();
343018197cf0dff5a9061f6065a8ecc108a0866dabSelim Cinek    private final float mDelayScale;
3515a77f7da856cbed19cb67c75268505a333352f1Jorim Jaggi
3615a77f7da856cbed19cb67c75268505a333352f1Jorim Jaggi    public AppearAnimationUtils(Context ctx) {
373018197cf0dff5a9061f6065a8ecc108a0866dabSelim Cinek        this(ctx, 1.0f, 1.0f);
383018197cf0dff5a9061f6065a8ecc108a0866dabSelim Cinek    }
393018197cf0dff5a9061f6065a8ecc108a0866dabSelim Cinek
403018197cf0dff5a9061f6065a8ecc108a0866dabSelim Cinek    public AppearAnimationUtils(Context ctx, float delayScaleFactor,
413018197cf0dff5a9061f6065a8ecc108a0866dabSelim Cinek            float translationScaleFactor) {
4215a77f7da856cbed19cb67c75268505a333352f1Jorim Jaggi        mLinearOutSlowIn = AnimationUtils.loadInterpolator(
4315a77f7da856cbed19cb67c75268505a333352f1Jorim Jaggi                ctx, android.R.interpolator.linear_out_slow_in);
443018197cf0dff5a9061f6065a8ecc108a0866dabSelim Cinek        mStartTranslation = ctx.getResources().getDimensionPixelOffset(
453018197cf0dff5a9061f6065a8ecc108a0866dabSelim Cinek                R.dimen.appear_y_translation_start) * translationScaleFactor;
463018197cf0dff5a9061f6065a8ecc108a0866dabSelim Cinek        mDelayScale = delayScaleFactor;
4715a77f7da856cbed19cb67c75268505a333352f1Jorim Jaggi    }
4815a77f7da856cbed19cb67c75268505a333352f1Jorim Jaggi
493018197cf0dff5a9061f6065a8ecc108a0866dabSelim Cinek    public void startAppearAnimation(View[][] objects, final Runnable finishListener) {
503018197cf0dff5a9061f6065a8ecc108a0866dabSelim Cinek        startAppearAnimation(objects, finishListener, this);
513018197cf0dff5a9061f6065a8ecc108a0866dabSelim Cinek    }
523018197cf0dff5a9061f6065a8ecc108a0866dabSelim Cinek
533018197cf0dff5a9061f6065a8ecc108a0866dabSelim Cinek    public <T> void startAppearAnimation(T[][] objects, final Runnable finishListener,
543018197cf0dff5a9061f6065a8ecc108a0866dabSelim Cinek            AppearAnimationCreator<T> creator) {
553018197cf0dff5a9061f6065a8ecc108a0866dabSelim Cinek        AppearAnimationProperties properties = getDelays(objects);
563018197cf0dff5a9061f6065a8ecc108a0866dabSelim Cinek        startAnimations(properties, objects, finishListener, creator);
573018197cf0dff5a9061f6065a8ecc108a0866dabSelim Cinek    }
583018197cf0dff5a9061f6065a8ecc108a0866dabSelim Cinek
593018197cf0dff5a9061f6065a8ecc108a0866dabSelim Cinek    private <T> void startAnimations(AppearAnimationProperties properties, T[][] objects,
603018197cf0dff5a9061f6065a8ecc108a0866dabSelim Cinek            final Runnable finishListener, AppearAnimationCreator creator) {;
613018197cf0dff5a9061f6065a8ecc108a0866dabSelim Cinek        if (properties.maxDelayRowIndex == -1 || properties.maxDelayColIndex == -1) {
623018197cf0dff5a9061f6065a8ecc108a0866dabSelim Cinek            finishListener.run();
633018197cf0dff5a9061f6065a8ecc108a0866dabSelim Cinek            return;
643018197cf0dff5a9061f6065a8ecc108a0866dabSelim Cinek        }
653018197cf0dff5a9061f6065a8ecc108a0866dabSelim Cinek        for (int row = 0; row < properties.delays.length; row++) {
663018197cf0dff5a9061f6065a8ecc108a0866dabSelim Cinek            long[] columns = properties.delays[row];
6715a77f7da856cbed19cb67c75268505a333352f1Jorim Jaggi            for (int col = 0; col < columns.length; col++) {
683018197cf0dff5a9061f6065a8ecc108a0866dabSelim Cinek                long delay = columns[col];
693018197cf0dff5a9061f6065a8ecc108a0866dabSelim Cinek                Runnable endRunnable = null;
703018197cf0dff5a9061f6065a8ecc108a0866dabSelim Cinek                if (properties.maxDelayRowIndex == row && properties.maxDelayColIndex == col) {
713018197cf0dff5a9061f6065a8ecc108a0866dabSelim Cinek                    endRunnable = finishListener;
7215a77f7da856cbed19cb67c75268505a333352f1Jorim Jaggi                }
733018197cf0dff5a9061f6065a8ecc108a0866dabSelim Cinek                creator.createAnimation(objects[row][col], delay, APPEAR_DURATION,
743018197cf0dff5a9061f6065a8ecc108a0866dabSelim Cinek                        mStartTranslation, mLinearOutSlowIn, endRunnable);
7515a77f7da856cbed19cb67c75268505a333352f1Jorim Jaggi            }
7615a77f7da856cbed19cb67c75268505a333352f1Jorim Jaggi        }
773018197cf0dff5a9061f6065a8ecc108a0866dabSelim Cinek
7815a77f7da856cbed19cb67c75268505a333352f1Jorim Jaggi    }
7915a77f7da856cbed19cb67c75268505a333352f1Jorim Jaggi
803018197cf0dff5a9061f6065a8ecc108a0866dabSelim Cinek    private <T> AppearAnimationProperties getDelays(T[][] items) {
813018197cf0dff5a9061f6065a8ecc108a0866dabSelim Cinek        long maxDelay = 0;
823018197cf0dff5a9061f6065a8ecc108a0866dabSelim Cinek        mProperties.maxDelayColIndex = -1;
833018197cf0dff5a9061f6065a8ecc108a0866dabSelim Cinek        mProperties.maxDelayRowIndex = -1;
843018197cf0dff5a9061f6065a8ecc108a0866dabSelim Cinek        mProperties.delays = new long[items.length][];
853018197cf0dff5a9061f6065a8ecc108a0866dabSelim Cinek        for (int row = 0; row < items.length; row++) {
863018197cf0dff5a9061f6065a8ecc108a0866dabSelim Cinek            T[] columns = items[row];
873018197cf0dff5a9061f6065a8ecc108a0866dabSelim Cinek            mProperties.delays[row] = new long[columns.length];
883018197cf0dff5a9061f6065a8ecc108a0866dabSelim Cinek            for (int col = 0; col < columns.length; col++) {
893018197cf0dff5a9061f6065a8ecc108a0866dabSelim Cinek                long delay = calculateDelay(row, col);
903018197cf0dff5a9061f6065a8ecc108a0866dabSelim Cinek                mProperties.delays[row][col] = delay;
913018197cf0dff5a9061f6065a8ecc108a0866dabSelim Cinek                if (items[row][col] != null && delay > maxDelay) {
923018197cf0dff5a9061f6065a8ecc108a0866dabSelim Cinek                    maxDelay = delay;
933018197cf0dff5a9061f6065a8ecc108a0866dabSelim Cinek                    mProperties.maxDelayColIndex = col;
943018197cf0dff5a9061f6065a8ecc108a0866dabSelim Cinek                    mProperties.maxDelayRowIndex = row;
953018197cf0dff5a9061f6065a8ecc108a0866dabSelim Cinek                }
963018197cf0dff5a9061f6065a8ecc108a0866dabSelim Cinek            }
9715a77f7da856cbed19cb67c75268505a333352f1Jorim Jaggi        }
983018197cf0dff5a9061f6065a8ecc108a0866dabSelim Cinek        return mProperties;
9915a77f7da856cbed19cb67c75268505a333352f1Jorim Jaggi    }
10015a77f7da856cbed19cb67c75268505a333352f1Jorim Jaggi
10115a77f7da856cbed19cb67c75268505a333352f1Jorim Jaggi    private long calculateDelay(int row, int col) {
1023018197cf0dff5a9061f6065a8ecc108a0866dabSelim Cinek        return (long) ((row * 40 + col * (Math.pow(row, 0.4) + 0.4) * 20) * mDelayScale);
10315a77f7da856cbed19cb67c75268505a333352f1Jorim Jaggi    }
10415a77f7da856cbed19cb67c75268505a333352f1Jorim Jaggi
1053018197cf0dff5a9061f6065a8ecc108a0866dabSelim Cinek    public Interpolator getInterpolator() {
10615a77f7da856cbed19cb67c75268505a333352f1Jorim Jaggi        return mLinearOutSlowIn;
10715a77f7da856cbed19cb67c75268505a333352f1Jorim Jaggi    }
10815a77f7da856cbed19cb67c75268505a333352f1Jorim Jaggi
10915a77f7da856cbed19cb67c75268505a333352f1Jorim Jaggi    public float getStartTranslation() {
11015a77f7da856cbed19cb67c75268505a333352f1Jorim Jaggi        return mStartTranslation;
11115a77f7da856cbed19cb67c75268505a333352f1Jorim Jaggi    }
1123018197cf0dff5a9061f6065a8ecc108a0866dabSelim Cinek
1133018197cf0dff5a9061f6065a8ecc108a0866dabSelim Cinek    @Override
1143018197cf0dff5a9061f6065a8ecc108a0866dabSelim Cinek    public void createAnimation(View view, long delay, long duration, float startTranslationY,
1153018197cf0dff5a9061f6065a8ecc108a0866dabSelim Cinek            Interpolator interpolator, Runnable endRunnable) {
1163018197cf0dff5a9061f6065a8ecc108a0866dabSelim Cinek        if (view != null) {
1173018197cf0dff5a9061f6065a8ecc108a0866dabSelim Cinek            view.setAlpha(0f);
1183018197cf0dff5a9061f6065a8ecc108a0866dabSelim Cinek            view.setTranslationY(startTranslationY);
1193018197cf0dff5a9061f6065a8ecc108a0866dabSelim Cinek            view.animate()
1203018197cf0dff5a9061f6065a8ecc108a0866dabSelim Cinek                    .alpha(1f)
1213018197cf0dff5a9061f6065a8ecc108a0866dabSelim Cinek                    .translationY(0)
1223018197cf0dff5a9061f6065a8ecc108a0866dabSelim Cinek                    .setInterpolator(interpolator)
1233018197cf0dff5a9061f6065a8ecc108a0866dabSelim Cinek                    .setDuration(duration)
1243018197cf0dff5a9061f6065a8ecc108a0866dabSelim Cinek                    .setStartDelay(delay);
1253018197cf0dff5a9061f6065a8ecc108a0866dabSelim Cinek            if (view.hasOverlappingRendering()) {
1263018197cf0dff5a9061f6065a8ecc108a0866dabSelim Cinek                view.animate().withLayer();
1273018197cf0dff5a9061f6065a8ecc108a0866dabSelim Cinek            }
1283018197cf0dff5a9061f6065a8ecc108a0866dabSelim Cinek            if (endRunnable != null) {
1293018197cf0dff5a9061f6065a8ecc108a0866dabSelim Cinek                view.animate().withEndAction(endRunnable);
1303018197cf0dff5a9061f6065a8ecc108a0866dabSelim Cinek            }
1313018197cf0dff5a9061f6065a8ecc108a0866dabSelim Cinek        }
1323018197cf0dff5a9061f6065a8ecc108a0866dabSelim Cinek    }
1333018197cf0dff5a9061f6065a8ecc108a0866dabSelim Cinek
1343018197cf0dff5a9061f6065a8ecc108a0866dabSelim Cinek    public class AppearAnimationProperties {
1353018197cf0dff5a9061f6065a8ecc108a0866dabSelim Cinek        public long[][] delays;
1363018197cf0dff5a9061f6065a8ecc108a0866dabSelim Cinek        public int maxDelayRowIndex;
1373018197cf0dff5a9061f6065a8ecc108a0866dabSelim Cinek        public int maxDelayColIndex;
1383018197cf0dff5a9061f6065a8ecc108a0866dabSelim Cinek    }
13915a77f7da856cbed19cb67c75268505a333352f1Jorim Jaggi}
140