Home | History | Annotate | Download | only in keyguard
      1 /*
      2  * Copyright (C) 2014 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 com.android.keyguard;
     18 
     19 import android.content.Context;
     20 import android.view.View;
     21 import android.view.animation.AnimationUtils;
     22 import android.view.animation.Interpolator;
     23 
     24 /**
     25  * A class to make nice appear transitions for views in a tabular layout.
     26  */
     27 public class AppearAnimationUtils implements AppearAnimationCreator<View> {
     28 
     29     public static final long DEFAULT_APPEAR_DURATION = 220;
     30 
     31     private final Interpolator mInterpolator;
     32     private final float mStartTranslation;
     33     private final AppearAnimationProperties mProperties = new AppearAnimationProperties();
     34     private final float mDelayScale;
     35     private final long mDuration;
     36 
     37     public AppearAnimationUtils(Context ctx) {
     38         this(ctx, DEFAULT_APPEAR_DURATION,
     39                 1.0f, 1.0f,
     40                 AnimationUtils.loadInterpolator(ctx, android.R.interpolator.linear_out_slow_in));
     41     }
     42 
     43     public AppearAnimationUtils(Context ctx, long duration, float translationScaleFactor,
     44             float delayScaleFactor, Interpolator interpolator) {
     45         mInterpolator = interpolator;
     46         mStartTranslation = ctx.getResources().getDimensionPixelOffset(
     47                 R.dimen.appear_y_translation_start) * translationScaleFactor;
     48         mDelayScale = delayScaleFactor;
     49         mDuration = duration;
     50     }
     51 
     52     public void startAppearAnimation(View[][] objects, final Runnable finishListener) {
     53         startAppearAnimation(objects, finishListener, this);
     54     }
     55 
     56     public void startAppearAnimation(View[] objects, final Runnable finishListener) {
     57         startAppearAnimation(objects, finishListener, this);
     58     }
     59 
     60     public <T> void startAppearAnimation(T[][] objects, final Runnable finishListener,
     61             AppearAnimationCreator<T> creator) {
     62         AppearAnimationProperties properties = getDelays(objects);
     63         startAnimations(properties, objects, finishListener, creator);
     64     }
     65 
     66     public <T> void startAppearAnimation(T[] objects, final Runnable finishListener,
     67             AppearAnimationCreator<T> creator) {
     68         AppearAnimationProperties properties = getDelays(objects);
     69         startAnimations(properties, objects, finishListener, creator);
     70     }
     71 
     72     private <T> void startAnimations(AppearAnimationProperties properties, T[] objects,
     73             final Runnable finishListener, AppearAnimationCreator<T> creator) {
     74         if (properties.maxDelayRowIndex == -1 || properties.maxDelayColIndex == -1) {
     75             finishListener.run();
     76             return;
     77         }
     78         for (int row = 0; row < properties.delays.length; row++) {
     79             long[] columns = properties.delays[row];
     80             long delay = columns[0];
     81             Runnable endRunnable = null;
     82             if (properties.maxDelayRowIndex == row && properties.maxDelayColIndex == 0) {
     83                 endRunnable = finishListener;
     84             }
     85             creator.createAnimation(objects[row], delay, mDuration,
     86                     mStartTranslation, mInterpolator, endRunnable);
     87         }
     88     }
     89 
     90     private <T> void startAnimations(AppearAnimationProperties properties, T[][] objects,
     91             final Runnable finishListener, AppearAnimationCreator<T> creator) {
     92         if (properties.maxDelayRowIndex == -1 || properties.maxDelayColIndex == -1) {
     93             finishListener.run();
     94             return;
     95         }
     96         for (int row = 0; row < properties.delays.length; row++) {
     97             long[] columns = properties.delays[row];
     98             for (int col = 0; col < columns.length; col++) {
     99                 long delay = columns[col];
    100                 Runnable endRunnable = null;
    101                 if (properties.maxDelayRowIndex == row && properties.maxDelayColIndex == col) {
    102                     endRunnable = finishListener;
    103                 }
    104                 creator.createAnimation(objects[row][col], delay, mDuration,
    105                         mStartTranslation, mInterpolator, endRunnable);
    106             }
    107         }
    108     }
    109 
    110     private <T> AppearAnimationProperties getDelays(T[] items) {
    111         long maxDelay = -1;
    112         mProperties.maxDelayColIndex = -1;
    113         mProperties.maxDelayRowIndex = -1;
    114         mProperties.delays = new long[items.length][];
    115         for (int row = 0; row < items.length; row++) {
    116             mProperties.delays[row] = new long[1];
    117             long delay = calculateDelay(row, 0);
    118             mProperties.delays[row][0] = delay;
    119             if (items[row] != null && delay > maxDelay) {
    120                 maxDelay = delay;
    121                 mProperties.maxDelayColIndex = 0;
    122                 mProperties.maxDelayRowIndex = row;
    123             }
    124         }
    125         return mProperties;
    126     }
    127 
    128     private <T> AppearAnimationProperties getDelays(T[][] items) {
    129         long maxDelay = -1;
    130         mProperties.maxDelayColIndex = -1;
    131         mProperties.maxDelayRowIndex = -1;
    132         mProperties.delays = new long[items.length][];
    133         for (int row = 0; row < items.length; row++) {
    134             T[] columns = items[row];
    135             mProperties.delays[row] = new long[columns.length];
    136             for (int col = 0; col < columns.length; col++) {
    137                 long delay = calculateDelay(row, col);
    138                 mProperties.delays[row][col] = delay;
    139                 if (items[row][col] != null && delay > maxDelay) {
    140                     maxDelay = delay;
    141                     mProperties.maxDelayColIndex = col;
    142                     mProperties.maxDelayRowIndex = row;
    143                 }
    144             }
    145         }
    146         return mProperties;
    147     }
    148 
    149     private long calculateDelay(int row, int col) {
    150         return (long) ((row * 40 + col * (Math.pow(row, 0.4) + 0.4) * 20) * mDelayScale);
    151     }
    152 
    153     public Interpolator getInterpolator() {
    154         return mInterpolator;
    155     }
    156 
    157     public float getStartTranslation() {
    158         return mStartTranslation;
    159     }
    160 
    161     @Override
    162     public void createAnimation(View view, long delay, long duration, float startTranslationY,
    163             Interpolator interpolator, Runnable endRunnable) {
    164         if (view != null) {
    165             view.setAlpha(0f);
    166             view.setTranslationY(startTranslationY);
    167             view.animate()
    168                     .alpha(1f)
    169                     .translationY(0)
    170                     .setInterpolator(interpolator)
    171                     .setDuration(duration)
    172                     .setStartDelay(delay);
    173             if (view.hasOverlappingRendering()) {
    174                 view.animate().withLayer();
    175             }
    176             if (endRunnable != null) {
    177                 view.animate().withEndAction(endRunnable);
    178             }
    179         }
    180     }
    181 
    182     public class AppearAnimationProperties {
    183         public long[][] delays;
    184         public int maxDelayRowIndex;
    185         public int maxDelayColIndex;
    186     }
    187 }
    188