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 2998f8530af3bb8636b7b173443c90686c485205d6Jorim Jaggi public static final long DEFAULT_APPEAR_DURATION = 220; 3015a77f7da856cbed19cb67c75268505a333352f1Jorim Jaggi 3198f8530af3bb8636b7b173443c90686c485205d6Jorim Jaggi private final Interpolator mInterpolator; 3215a77f7da856cbed19cb67c75268505a333352f1Jorim Jaggi private final float mStartTranslation; 333018197cf0dff5a9061f6065a8ecc108a0866dabSelim Cinek private final AppearAnimationProperties mProperties = new AppearAnimationProperties(); 34f9c0e8f02f3483d6aa9e762c97a2c02ea50eeb02Selim Cinek protected final float mDelayScale; 3598f8530af3bb8636b7b173443c90686c485205d6Jorim Jaggi private final long mDuration; 36f9c0e8f02f3483d6aa9e762c97a2c02ea50eeb02Selim Cinek protected boolean mScaleTranslationWithRow; 37f9c0e8f02f3483d6aa9e762c97a2c02ea50eeb02Selim Cinek protected boolean mAppearing; 3815a77f7da856cbed19cb67c75268505a333352f1Jorim Jaggi 3915a77f7da856cbed19cb67c75268505a333352f1Jorim Jaggi public AppearAnimationUtils(Context ctx) { 4098f8530af3bb8636b7b173443c90686c485205d6Jorim Jaggi this(ctx, DEFAULT_APPEAR_DURATION, 4176a1623afc170a13923b68f3256057d8adeb7937Jorim Jaggi 1.0f, 1.0f, 4298f8530af3bb8636b7b173443c90686c485205d6Jorim Jaggi AnimationUtils.loadInterpolator(ctx, android.R.interpolator.linear_out_slow_in)); 433018197cf0dff5a9061f6065a8ecc108a0866dabSelim Cinek } 443018197cf0dff5a9061f6065a8ecc108a0866dabSelim Cinek 4598f8530af3bb8636b7b173443c90686c485205d6Jorim Jaggi public AppearAnimationUtils(Context ctx, long duration, float translationScaleFactor, 4698f8530af3bb8636b7b173443c90686c485205d6Jorim Jaggi float delayScaleFactor, Interpolator interpolator) { 4798f8530af3bb8636b7b173443c90686c485205d6Jorim Jaggi mInterpolator = interpolator; 483018197cf0dff5a9061f6065a8ecc108a0866dabSelim Cinek mStartTranslation = ctx.getResources().getDimensionPixelOffset( 493018197cf0dff5a9061f6065a8ecc108a0866dabSelim Cinek R.dimen.appear_y_translation_start) * translationScaleFactor; 503018197cf0dff5a9061f6065a8ecc108a0866dabSelim Cinek mDelayScale = delayScaleFactor; 5198f8530af3bb8636b7b173443c90686c485205d6Jorim Jaggi mDuration = duration; 52f9c0e8f02f3483d6aa9e762c97a2c02ea50eeb02Selim Cinek mScaleTranslationWithRow = false; 53f9c0e8f02f3483d6aa9e762c97a2c02ea50eeb02Selim Cinek mAppearing = true; 5415a77f7da856cbed19cb67c75268505a333352f1Jorim Jaggi } 5515a77f7da856cbed19cb67c75268505a333352f1Jorim Jaggi 56f9c0e8f02f3483d6aa9e762c97a2c02ea50eeb02Selim Cinek public void startAnimation(View[][] objects, final Runnable finishListener) { 57f9c0e8f02f3483d6aa9e762c97a2c02ea50eeb02Selim Cinek startAnimation(objects, finishListener, this); 583018197cf0dff5a9061f6065a8ecc108a0866dabSelim Cinek } 593018197cf0dff5a9061f6065a8ecc108a0866dabSelim Cinek 60f9c0e8f02f3483d6aa9e762c97a2c02ea50eeb02Selim Cinek public void startAnimation(View[] objects, final Runnable finishListener) { 61f9c0e8f02f3483d6aa9e762c97a2c02ea50eeb02Selim Cinek startAnimation(objects, finishListener, this); 6298f8530af3bb8636b7b173443c90686c485205d6Jorim Jaggi } 6398f8530af3bb8636b7b173443c90686c485205d6Jorim Jaggi 64f9c0e8f02f3483d6aa9e762c97a2c02ea50eeb02Selim Cinek public <T> void startAnimation(T[][] objects, final Runnable finishListener, 653018197cf0dff5a9061f6065a8ecc108a0866dabSelim Cinek AppearAnimationCreator<T> creator) { 663018197cf0dff5a9061f6065a8ecc108a0866dabSelim Cinek AppearAnimationProperties properties = getDelays(objects); 673018197cf0dff5a9061f6065a8ecc108a0866dabSelim Cinek startAnimations(properties, objects, finishListener, creator); 683018197cf0dff5a9061f6065a8ecc108a0866dabSelim Cinek } 693018197cf0dff5a9061f6065a8ecc108a0866dabSelim Cinek 70f9c0e8f02f3483d6aa9e762c97a2c02ea50eeb02Selim Cinek public <T> void startAnimation(T[] objects, final Runnable finishListener, 7198f8530af3bb8636b7b173443c90686c485205d6Jorim Jaggi AppearAnimationCreator<T> creator) { 7298f8530af3bb8636b7b173443c90686c485205d6Jorim Jaggi AppearAnimationProperties properties = getDelays(objects); 7398f8530af3bb8636b7b173443c90686c485205d6Jorim Jaggi startAnimations(properties, objects, finishListener, creator); 7498f8530af3bb8636b7b173443c90686c485205d6Jorim Jaggi } 7598f8530af3bb8636b7b173443c90686c485205d6Jorim Jaggi 7698f8530af3bb8636b7b173443c90686c485205d6Jorim Jaggi private <T> void startAnimations(AppearAnimationProperties properties, T[] objects, 7798f8530af3bb8636b7b173443c90686c485205d6Jorim Jaggi final Runnable finishListener, AppearAnimationCreator<T> creator) { 7898f8530af3bb8636b7b173443c90686c485205d6Jorim Jaggi if (properties.maxDelayRowIndex == -1 || properties.maxDelayColIndex == -1) { 7998f8530af3bb8636b7b173443c90686c485205d6Jorim Jaggi finishListener.run(); 8098f8530af3bb8636b7b173443c90686c485205d6Jorim Jaggi return; 8198f8530af3bb8636b7b173443c90686c485205d6Jorim Jaggi } 8298f8530af3bb8636b7b173443c90686c485205d6Jorim Jaggi for (int row = 0; row < properties.delays.length; row++) { 8398f8530af3bb8636b7b173443c90686c485205d6Jorim Jaggi long[] columns = properties.delays[row]; 8498f8530af3bb8636b7b173443c90686c485205d6Jorim Jaggi long delay = columns[0]; 8598f8530af3bb8636b7b173443c90686c485205d6Jorim Jaggi Runnable endRunnable = null; 8698f8530af3bb8636b7b173443c90686c485205d6Jorim Jaggi if (properties.maxDelayRowIndex == row && properties.maxDelayColIndex == 0) { 8798f8530af3bb8636b7b173443c90686c485205d6Jorim Jaggi endRunnable = finishListener; 8898f8530af3bb8636b7b173443c90686c485205d6Jorim Jaggi } 8998f8530af3bb8636b7b173443c90686c485205d6Jorim Jaggi creator.createAnimation(objects[row], delay, mDuration, 90f9c0e8f02f3483d6aa9e762c97a2c02ea50eeb02Selim Cinek mStartTranslation, true /* appearing */, mInterpolator, endRunnable); 9198f8530af3bb8636b7b173443c90686c485205d6Jorim Jaggi } 9298f8530af3bb8636b7b173443c90686c485205d6Jorim Jaggi } 9398f8530af3bb8636b7b173443c90686c485205d6Jorim Jaggi 943018197cf0dff5a9061f6065a8ecc108a0866dabSelim Cinek private <T> void startAnimations(AppearAnimationProperties properties, T[][] objects, 9598f8530af3bb8636b7b173443c90686c485205d6Jorim Jaggi final Runnable finishListener, AppearAnimationCreator<T> creator) { 963018197cf0dff5a9061f6065a8ecc108a0866dabSelim Cinek if (properties.maxDelayRowIndex == -1 || properties.maxDelayColIndex == -1) { 973018197cf0dff5a9061f6065a8ecc108a0866dabSelim Cinek finishListener.run(); 983018197cf0dff5a9061f6065a8ecc108a0866dabSelim Cinek return; 993018197cf0dff5a9061f6065a8ecc108a0866dabSelim Cinek } 1003018197cf0dff5a9061f6065a8ecc108a0866dabSelim Cinek for (int row = 0; row < properties.delays.length; row++) { 1013018197cf0dff5a9061f6065a8ecc108a0866dabSelim Cinek long[] columns = properties.delays[row]; 102f9c0e8f02f3483d6aa9e762c97a2c02ea50eeb02Selim Cinek float translation = mScaleTranslationWithRow 103f9c0e8f02f3483d6aa9e762c97a2c02ea50eeb02Selim Cinek ? (float) (Math.pow((properties.delays.length - row), 2) 104f9c0e8f02f3483d6aa9e762c97a2c02ea50eeb02Selim Cinek / properties.delays.length * mStartTranslation) 105f9c0e8f02f3483d6aa9e762c97a2c02ea50eeb02Selim Cinek : mStartTranslation; 10615a77f7da856cbed19cb67c75268505a333352f1Jorim Jaggi for (int col = 0; col < columns.length; col++) { 1073018197cf0dff5a9061f6065a8ecc108a0866dabSelim Cinek long delay = columns[col]; 1083018197cf0dff5a9061f6065a8ecc108a0866dabSelim Cinek Runnable endRunnable = null; 1093018197cf0dff5a9061f6065a8ecc108a0866dabSelim Cinek if (properties.maxDelayRowIndex == row && properties.maxDelayColIndex == col) { 1103018197cf0dff5a9061f6065a8ecc108a0866dabSelim Cinek endRunnable = finishListener; 11115a77f7da856cbed19cb67c75268505a333352f1Jorim Jaggi } 11298f8530af3bb8636b7b173443c90686c485205d6Jorim Jaggi creator.createAnimation(objects[row][col], delay, mDuration, 113f9c0e8f02f3483d6aa9e762c97a2c02ea50eeb02Selim Cinek mAppearing ? translation : -translation, 114f9c0e8f02f3483d6aa9e762c97a2c02ea50eeb02Selim Cinek mAppearing, mInterpolator, endRunnable); 11515a77f7da856cbed19cb67c75268505a333352f1Jorim Jaggi } 11615a77f7da856cbed19cb67c75268505a333352f1Jorim Jaggi } 11798f8530af3bb8636b7b173443c90686c485205d6Jorim Jaggi } 1183018197cf0dff5a9061f6065a8ecc108a0866dabSelim Cinek 11998f8530af3bb8636b7b173443c90686c485205d6Jorim Jaggi private <T> AppearAnimationProperties getDelays(T[] items) { 12098f8530af3bb8636b7b173443c90686c485205d6Jorim Jaggi long maxDelay = -1; 12198f8530af3bb8636b7b173443c90686c485205d6Jorim Jaggi mProperties.maxDelayColIndex = -1; 12298f8530af3bb8636b7b173443c90686c485205d6Jorim Jaggi mProperties.maxDelayRowIndex = -1; 12398f8530af3bb8636b7b173443c90686c485205d6Jorim Jaggi mProperties.delays = new long[items.length][]; 12498f8530af3bb8636b7b173443c90686c485205d6Jorim Jaggi for (int row = 0; row < items.length; row++) { 12598f8530af3bb8636b7b173443c90686c485205d6Jorim Jaggi mProperties.delays[row] = new long[1]; 12698f8530af3bb8636b7b173443c90686c485205d6Jorim Jaggi long delay = calculateDelay(row, 0); 12798f8530af3bb8636b7b173443c90686c485205d6Jorim Jaggi mProperties.delays[row][0] = delay; 12898f8530af3bb8636b7b173443c90686c485205d6Jorim Jaggi if (items[row] != null && delay > maxDelay) { 12998f8530af3bb8636b7b173443c90686c485205d6Jorim Jaggi maxDelay = delay; 13098f8530af3bb8636b7b173443c90686c485205d6Jorim Jaggi mProperties.maxDelayColIndex = 0; 13198f8530af3bb8636b7b173443c90686c485205d6Jorim Jaggi mProperties.maxDelayRowIndex = row; 13298f8530af3bb8636b7b173443c90686c485205d6Jorim Jaggi } 13398f8530af3bb8636b7b173443c90686c485205d6Jorim Jaggi } 13498f8530af3bb8636b7b173443c90686c485205d6Jorim Jaggi return mProperties; 13515a77f7da856cbed19cb67c75268505a333352f1Jorim Jaggi } 13615a77f7da856cbed19cb67c75268505a333352f1Jorim Jaggi 1373018197cf0dff5a9061f6065a8ecc108a0866dabSelim Cinek private <T> AppearAnimationProperties getDelays(T[][] items) { 13898f8530af3bb8636b7b173443c90686c485205d6Jorim Jaggi long maxDelay = -1; 1393018197cf0dff5a9061f6065a8ecc108a0866dabSelim Cinek mProperties.maxDelayColIndex = -1; 1403018197cf0dff5a9061f6065a8ecc108a0866dabSelim Cinek mProperties.maxDelayRowIndex = -1; 1413018197cf0dff5a9061f6065a8ecc108a0866dabSelim Cinek mProperties.delays = new long[items.length][]; 1423018197cf0dff5a9061f6065a8ecc108a0866dabSelim Cinek for (int row = 0; row < items.length; row++) { 1433018197cf0dff5a9061f6065a8ecc108a0866dabSelim Cinek T[] columns = items[row]; 1443018197cf0dff5a9061f6065a8ecc108a0866dabSelim Cinek mProperties.delays[row] = new long[columns.length]; 1453018197cf0dff5a9061f6065a8ecc108a0866dabSelim Cinek for (int col = 0; col < columns.length; col++) { 1463018197cf0dff5a9061f6065a8ecc108a0866dabSelim Cinek long delay = calculateDelay(row, col); 1473018197cf0dff5a9061f6065a8ecc108a0866dabSelim Cinek mProperties.delays[row][col] = delay; 1483018197cf0dff5a9061f6065a8ecc108a0866dabSelim Cinek if (items[row][col] != null && delay > maxDelay) { 1493018197cf0dff5a9061f6065a8ecc108a0866dabSelim Cinek maxDelay = delay; 1503018197cf0dff5a9061f6065a8ecc108a0866dabSelim Cinek mProperties.maxDelayColIndex = col; 1513018197cf0dff5a9061f6065a8ecc108a0866dabSelim Cinek mProperties.maxDelayRowIndex = row; 1523018197cf0dff5a9061f6065a8ecc108a0866dabSelim Cinek } 1533018197cf0dff5a9061f6065a8ecc108a0866dabSelim Cinek } 15415a77f7da856cbed19cb67c75268505a333352f1Jorim Jaggi } 1553018197cf0dff5a9061f6065a8ecc108a0866dabSelim Cinek return mProperties; 15615a77f7da856cbed19cb67c75268505a333352f1Jorim Jaggi } 15715a77f7da856cbed19cb67c75268505a333352f1Jorim Jaggi 158f9c0e8f02f3483d6aa9e762c97a2c02ea50eeb02Selim Cinek protected long calculateDelay(int row, int col) { 1593018197cf0dff5a9061f6065a8ecc108a0866dabSelim Cinek return (long) ((row * 40 + col * (Math.pow(row, 0.4) + 0.4) * 20) * mDelayScale); 16015a77f7da856cbed19cb67c75268505a333352f1Jorim Jaggi } 16115a77f7da856cbed19cb67c75268505a333352f1Jorim Jaggi 1623018197cf0dff5a9061f6065a8ecc108a0866dabSelim Cinek public Interpolator getInterpolator() { 16398f8530af3bb8636b7b173443c90686c485205d6Jorim Jaggi return mInterpolator; 16415a77f7da856cbed19cb67c75268505a333352f1Jorim Jaggi } 16515a77f7da856cbed19cb67c75268505a333352f1Jorim Jaggi 16615a77f7da856cbed19cb67c75268505a333352f1Jorim Jaggi public float getStartTranslation() { 16715a77f7da856cbed19cb67c75268505a333352f1Jorim Jaggi return mStartTranslation; 16815a77f7da856cbed19cb67c75268505a333352f1Jorim Jaggi } 1693018197cf0dff5a9061f6065a8ecc108a0866dabSelim Cinek 1703018197cf0dff5a9061f6065a8ecc108a0866dabSelim Cinek @Override 171f9c0e8f02f3483d6aa9e762c97a2c02ea50eeb02Selim Cinek public void createAnimation(View view, long delay, long duration, float translationY, 172f9c0e8f02f3483d6aa9e762c97a2c02ea50eeb02Selim Cinek boolean appearing, Interpolator interpolator, Runnable endRunnable) { 1733018197cf0dff5a9061f6065a8ecc108a0866dabSelim Cinek if (view != null) { 174f9c0e8f02f3483d6aa9e762c97a2c02ea50eeb02Selim Cinek view.setAlpha(appearing ? 0f : 1.0f); 175f9c0e8f02f3483d6aa9e762c97a2c02ea50eeb02Selim Cinek view.setTranslationY(appearing ? translationY : 0); 1763018197cf0dff5a9061f6065a8ecc108a0866dabSelim Cinek view.animate() 177f9c0e8f02f3483d6aa9e762c97a2c02ea50eeb02Selim Cinek .alpha(appearing ? 1f : 0f) 178f9c0e8f02f3483d6aa9e762c97a2c02ea50eeb02Selim Cinek .translationY(appearing ? 0 : translationY) 1793018197cf0dff5a9061f6065a8ecc108a0866dabSelim Cinek .setInterpolator(interpolator) 1803018197cf0dff5a9061f6065a8ecc108a0866dabSelim Cinek .setDuration(duration) 1813018197cf0dff5a9061f6065a8ecc108a0866dabSelim Cinek .setStartDelay(delay); 1823018197cf0dff5a9061f6065a8ecc108a0866dabSelim Cinek if (view.hasOverlappingRendering()) { 1833018197cf0dff5a9061f6065a8ecc108a0866dabSelim Cinek view.animate().withLayer(); 1843018197cf0dff5a9061f6065a8ecc108a0866dabSelim Cinek } 1853018197cf0dff5a9061f6065a8ecc108a0866dabSelim Cinek if (endRunnable != null) { 1863018197cf0dff5a9061f6065a8ecc108a0866dabSelim Cinek view.animate().withEndAction(endRunnable); 1873018197cf0dff5a9061f6065a8ecc108a0866dabSelim Cinek } 1883018197cf0dff5a9061f6065a8ecc108a0866dabSelim Cinek } 1893018197cf0dff5a9061f6065a8ecc108a0866dabSelim Cinek } 1903018197cf0dff5a9061f6065a8ecc108a0866dabSelim Cinek 1913018197cf0dff5a9061f6065a8ecc108a0866dabSelim Cinek public class AppearAnimationProperties { 1923018197cf0dff5a9061f6065a8ecc108a0866dabSelim Cinek public long[][] delays; 1933018197cf0dff5a9061f6065a8ecc108a0866dabSelim Cinek public int maxDelayRowIndex; 1943018197cf0dff5a9061f6065a8ecc108a0866dabSelim Cinek public int maxDelayColIndex; 1953018197cf0dff5a9061f6065a8ecc108a0866dabSelim Cinek } 19615a77f7da856cbed19cb67c75268505a333352f1Jorim Jaggi} 197