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