FlingAnimationUtils.java revision b6cdcbc66b4b862f83afde85b8e7109b6450b15e
187cd5e71ec087e191b8baaa8913a878f92d4e10dJorim Jaggi/* 287cd5e71ec087e191b8baaa8913a878f92d4e10dJorim Jaggi * Copyright (C) 2014 The Android Open Source Project 387cd5e71ec087e191b8baaa8913a878f92d4e10dJorim Jaggi * 487cd5e71ec087e191b8baaa8913a878f92d4e10dJorim Jaggi * Licensed under the Apache License, Version 2.0 (the "License"); 587cd5e71ec087e191b8baaa8913a878f92d4e10dJorim Jaggi * you may not use this file except in compliance with the License. 687cd5e71ec087e191b8baaa8913a878f92d4e10dJorim Jaggi * You may obtain a copy of the License at 787cd5e71ec087e191b8baaa8913a878f92d4e10dJorim Jaggi * 887cd5e71ec087e191b8baaa8913a878f92d4e10dJorim Jaggi * http://www.apache.org/licenses/LICENSE-2.0 987cd5e71ec087e191b8baaa8913a878f92d4e10dJorim Jaggi * 1087cd5e71ec087e191b8baaa8913a878f92d4e10dJorim Jaggi * Unless required by applicable law or agreed to in writing, software 1187cd5e71ec087e191b8baaa8913a878f92d4e10dJorim Jaggi * distributed under the License is distributed on an "AS IS" BASIS, 1287cd5e71ec087e191b8baaa8913a878f92d4e10dJorim Jaggi * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1387cd5e71ec087e191b8baaa8913a878f92d4e10dJorim Jaggi * See the License for the specific language governing permissions and 1487cd5e71ec087e191b8baaa8913a878f92d4e10dJorim Jaggi * limitations under the License 1587cd5e71ec087e191b8baaa8913a878f92d4e10dJorim Jaggi */ 1687cd5e71ec087e191b8baaa8913a878f92d4e10dJorim Jaggi 1787cd5e71ec087e191b8baaa8913a878f92d4e10dJorim Jaggipackage com.android.systemui.statusbar; 1887cd5e71ec087e191b8baaa8913a878f92d4e10dJorim Jaggi 19b6cdcbc66b4b862f83afde85b8e7109b6450b15eJorim Jaggiimport android.animation.Animator; 2087cd5e71ec087e191b8baaa8913a878f92d4e10dJorim Jaggiimport android.animation.ValueAnimator; 2187cd5e71ec087e191b8baaa8913a878f92d4e10dJorim Jaggiimport android.content.Context; 224c6969a512cd70831249ec1d07691f16fe5465f5Selim Cinekimport android.view.ViewPropertyAnimator; 2387cd5e71ec087e191b8baaa8913a878f92d4e10dJorim Jaggiimport android.view.animation.AnimationUtils; 2487cd5e71ec087e191b8baaa8913a878f92d4e10dJorim Jaggiimport android.view.animation.Interpolator; 2587cd5e71ec087e191b8baaa8913a878f92d4e10dJorim Jaggiimport android.view.animation.PathInterpolator; 2687cd5e71ec087e191b8baaa8913a878f92d4e10dJorim Jaggi 2787cd5e71ec087e191b8baaa8913a878f92d4e10dJorim Jaggi/** 2887cd5e71ec087e191b8baaa8913a878f92d4e10dJorim Jaggi * Utility class to calculate general fling animation when the finger is released. 2987cd5e71ec087e191b8baaa8913a878f92d4e10dJorim Jaggi */ 3087cd5e71ec087e191b8baaa8913a878f92d4e10dJorim Jaggipublic class FlingAnimationUtils { 3187cd5e71ec087e191b8baaa8913a878f92d4e10dJorim Jaggi 321d480695df31f1c328473f32d5007cea6a03b6e0Jorim Jaggi private static final float LINEAR_OUT_SLOW_IN_X2 = 0.35f; 332580a976ec93a01ed00fae51364ad872bc591d95Jorim Jaggi private static final float LINEAR_OUT_FASTER_IN_X2 = 0.5f; 342580a976ec93a01ed00fae51364ad872bc591d95Jorim Jaggi private static final float LINEAR_OUT_FASTER_IN_Y2_MIN = 0.4f; 352580a976ec93a01ed00fae51364ad872bc591d95Jorim Jaggi private static final float LINEAR_OUT_FASTER_IN_Y2_MAX = 0.5f; 3687cd5e71ec087e191b8baaa8913a878f92d4e10dJorim Jaggi private static final float MIN_VELOCITY_DP_PER_SECOND = 250; 37efbd7e3bb8244efae2561f0d9d7cedb36b1730bdJorim Jaggi private static final float HIGH_VELOCITY_DP_PER_SECOND = 3000; 3887cd5e71ec087e191b8baaa8913a878f92d4e10dJorim Jaggi 3987cd5e71ec087e191b8baaa8913a878f92d4e10dJorim Jaggi /** 4087cd5e71ec087e191b8baaa8913a878f92d4e10dJorim Jaggi * Crazy math. http://en.wikipedia.org/wiki/B%C3%A9zier_curve 4187cd5e71ec087e191b8baaa8913a878f92d4e10dJorim Jaggi */ 421d480695df31f1c328473f32d5007cea6a03b6e0Jorim Jaggi private static final float LINEAR_OUT_SLOW_IN_START_GRADIENT = 1.0f / LINEAR_OUT_SLOW_IN_X2; 4387cd5e71ec087e191b8baaa8913a878f92d4e10dJorim Jaggi 4487cd5e71ec087e191b8baaa8913a878f92d4e10dJorim Jaggi private Interpolator mLinearOutSlowIn; 4587cd5e71ec087e191b8baaa8913a878f92d4e10dJorim Jaggi private Interpolator mFastOutSlowIn; 461d480695df31f1c328473f32d5007cea6a03b6e0Jorim Jaggi private Interpolator mFastOutLinearIn; 471d480695df31f1c328473f32d5007cea6a03b6e0Jorim Jaggi 4887cd5e71ec087e191b8baaa8913a878f92d4e10dJorim Jaggi private float mMinVelocityPxPerSecond; 491d480695df31f1c328473f32d5007cea6a03b6e0Jorim Jaggi private float mMaxLengthSeconds; 50efbd7e3bb8244efae2561f0d9d7cedb36b1730bdJorim Jaggi private float mHighVelocityPxPerSecond; 5187cd5e71ec087e191b8baaa8913a878f92d4e10dJorim Jaggi 524c6969a512cd70831249ec1d07691f16fe5465f5Selim Cinek private AnimatorProperties mAnimatorProperties = new AnimatorProperties(); 534c6969a512cd70831249ec1d07691f16fe5465f5Selim Cinek 541d480695df31f1c328473f32d5007cea6a03b6e0Jorim Jaggi public FlingAnimationUtils(Context ctx, float maxLengthSeconds) { 551d480695df31f1c328473f32d5007cea6a03b6e0Jorim Jaggi mMaxLengthSeconds = maxLengthSeconds; 561d480695df31f1c328473f32d5007cea6a03b6e0Jorim Jaggi mLinearOutSlowIn = new PathInterpolator(0, 0, LINEAR_OUT_SLOW_IN_X2, 1); 5787cd5e71ec087e191b8baaa8913a878f92d4e10dJorim Jaggi mFastOutSlowIn 5887cd5e71ec087e191b8baaa8913a878f92d4e10dJorim Jaggi = AnimationUtils.loadInterpolator(ctx, android.R.interpolator.fast_out_slow_in); 591d480695df31f1c328473f32d5007cea6a03b6e0Jorim Jaggi mFastOutLinearIn 601d480695df31f1c328473f32d5007cea6a03b6e0Jorim Jaggi = AnimationUtils.loadInterpolator(ctx, android.R.interpolator.fast_out_linear_in); 6187cd5e71ec087e191b8baaa8913a878f92d4e10dJorim Jaggi mMinVelocityPxPerSecond 6287cd5e71ec087e191b8baaa8913a878f92d4e10dJorim Jaggi = MIN_VELOCITY_DP_PER_SECOND * ctx.getResources().getDisplayMetrics().density; 63efbd7e3bb8244efae2561f0d9d7cedb36b1730bdJorim Jaggi mHighVelocityPxPerSecond 64efbd7e3bb8244efae2561f0d9d7cedb36b1730bdJorim Jaggi = HIGH_VELOCITY_DP_PER_SECOND * ctx.getResources().getDisplayMetrics().density; 6587cd5e71ec087e191b8baaa8913a878f92d4e10dJorim Jaggi } 6687cd5e71ec087e191b8baaa8913a878f92d4e10dJorim Jaggi 6787cd5e71ec087e191b8baaa8913a878f92d4e10dJorim Jaggi /** 6887cd5e71ec087e191b8baaa8913a878f92d4e10dJorim Jaggi * Applies the interpolator and length to the animator, such that the fling animation is 6987cd5e71ec087e191b8baaa8913a878f92d4e10dJorim Jaggi * consistent with the finger motion. 7087cd5e71ec087e191b8baaa8913a878f92d4e10dJorim Jaggi * 7187cd5e71ec087e191b8baaa8913a878f92d4e10dJorim Jaggi * @param animator the animator to apply 7287cd5e71ec087e191b8baaa8913a878f92d4e10dJorim Jaggi * @param currValue the current value 7387cd5e71ec087e191b8baaa8913a878f92d4e10dJorim Jaggi * @param endValue the end value of the animator 7487cd5e71ec087e191b8baaa8913a878f92d4e10dJorim Jaggi * @param velocity the current velocity of the motion 7587cd5e71ec087e191b8baaa8913a878f92d4e10dJorim Jaggi */ 76b6cdcbc66b4b862f83afde85b8e7109b6450b15eJorim Jaggi public void apply(Animator animator, float currValue, float endValue, float velocity) { 771d480695df31f1c328473f32d5007cea6a03b6e0Jorim Jaggi apply(animator, currValue, endValue, velocity, Math.abs(endValue - currValue)); 781d480695df31f1c328473f32d5007cea6a03b6e0Jorim Jaggi } 791d480695df31f1c328473f32d5007cea6a03b6e0Jorim Jaggi 801d480695df31f1c328473f32d5007cea6a03b6e0Jorim Jaggi /** 811d480695df31f1c328473f32d5007cea6a03b6e0Jorim Jaggi * Applies the interpolator and length to the animator, such that the fling animation is 821d480695df31f1c328473f32d5007cea6a03b6e0Jorim Jaggi * consistent with the finger motion. 831d480695df31f1c328473f32d5007cea6a03b6e0Jorim Jaggi * 841d480695df31f1c328473f32d5007cea6a03b6e0Jorim Jaggi * @param animator the animator to apply 851d480695df31f1c328473f32d5007cea6a03b6e0Jorim Jaggi * @param currValue the current value 861d480695df31f1c328473f32d5007cea6a03b6e0Jorim Jaggi * @param endValue the end value of the animator 871d480695df31f1c328473f32d5007cea6a03b6e0Jorim Jaggi * @param velocity the current velocity of the motion 884c6969a512cd70831249ec1d07691f16fe5465f5Selim Cinek */ 894c6969a512cd70831249ec1d07691f16fe5465f5Selim Cinek public void apply(ViewPropertyAnimator animator, float currValue, float endValue, 904c6969a512cd70831249ec1d07691f16fe5465f5Selim Cinek float velocity) { 914c6969a512cd70831249ec1d07691f16fe5465f5Selim Cinek apply(animator, currValue, endValue, velocity, Math.abs(endValue - currValue)); 924c6969a512cd70831249ec1d07691f16fe5465f5Selim Cinek } 934c6969a512cd70831249ec1d07691f16fe5465f5Selim Cinek 944c6969a512cd70831249ec1d07691f16fe5465f5Selim Cinek /** 954c6969a512cd70831249ec1d07691f16fe5465f5Selim Cinek * Applies the interpolator and length to the animator, such that the fling animation is 964c6969a512cd70831249ec1d07691f16fe5465f5Selim Cinek * consistent with the finger motion. 974c6969a512cd70831249ec1d07691f16fe5465f5Selim Cinek * 984c6969a512cd70831249ec1d07691f16fe5465f5Selim Cinek * @param animator the animator to apply 994c6969a512cd70831249ec1d07691f16fe5465f5Selim Cinek * @param currValue the current value 1004c6969a512cd70831249ec1d07691f16fe5465f5Selim Cinek * @param endValue the end value of the animator 1014c6969a512cd70831249ec1d07691f16fe5465f5Selim Cinek * @param velocity the current velocity of the motion 1021d480695df31f1c328473f32d5007cea6a03b6e0Jorim Jaggi * @param maxDistance the maximum distance for this interaction; the maximum animation length 1031d480695df31f1c328473f32d5007cea6a03b6e0Jorim Jaggi * gets multiplied by the ratio between the actual distance and this value 1041d480695df31f1c328473f32d5007cea6a03b6e0Jorim Jaggi */ 105b6cdcbc66b4b862f83afde85b8e7109b6450b15eJorim Jaggi public void apply(Animator animator, float currValue, float endValue, float velocity, 1061d480695df31f1c328473f32d5007cea6a03b6e0Jorim Jaggi float maxDistance) { 1074c6969a512cd70831249ec1d07691f16fe5465f5Selim Cinek AnimatorProperties properties = getProperties(currValue, endValue, velocity, 1084c6969a512cd70831249ec1d07691f16fe5465f5Selim Cinek maxDistance); 1094c6969a512cd70831249ec1d07691f16fe5465f5Selim Cinek animator.setDuration(properties.duration); 1104c6969a512cd70831249ec1d07691f16fe5465f5Selim Cinek animator.setInterpolator(properties.interpolator); 1114c6969a512cd70831249ec1d07691f16fe5465f5Selim Cinek } 1124c6969a512cd70831249ec1d07691f16fe5465f5Selim Cinek 1134c6969a512cd70831249ec1d07691f16fe5465f5Selim Cinek /** 1144c6969a512cd70831249ec1d07691f16fe5465f5Selim Cinek * Applies the interpolator and length to the animator, such that the fling animation is 1154c6969a512cd70831249ec1d07691f16fe5465f5Selim Cinek * consistent with the finger motion. 1164c6969a512cd70831249ec1d07691f16fe5465f5Selim Cinek * 1174c6969a512cd70831249ec1d07691f16fe5465f5Selim Cinek * @param animator the animator to apply 1184c6969a512cd70831249ec1d07691f16fe5465f5Selim Cinek * @param currValue the current value 1194c6969a512cd70831249ec1d07691f16fe5465f5Selim Cinek * @param endValue the end value of the animator 1204c6969a512cd70831249ec1d07691f16fe5465f5Selim Cinek * @param velocity the current velocity of the motion 1214c6969a512cd70831249ec1d07691f16fe5465f5Selim Cinek * @param maxDistance the maximum distance for this interaction; the maximum animation length 1224c6969a512cd70831249ec1d07691f16fe5465f5Selim Cinek * gets multiplied by the ratio between the actual distance and this value 1234c6969a512cd70831249ec1d07691f16fe5465f5Selim Cinek */ 1244c6969a512cd70831249ec1d07691f16fe5465f5Selim Cinek public void apply(ViewPropertyAnimator animator, float currValue, float endValue, 1254c6969a512cd70831249ec1d07691f16fe5465f5Selim Cinek float velocity, float maxDistance) { 1264c6969a512cd70831249ec1d07691f16fe5465f5Selim Cinek AnimatorProperties properties = getProperties(currValue, endValue, velocity, 1274c6969a512cd70831249ec1d07691f16fe5465f5Selim Cinek maxDistance); 1284c6969a512cd70831249ec1d07691f16fe5465f5Selim Cinek animator.setDuration(properties.duration); 1294c6969a512cd70831249ec1d07691f16fe5465f5Selim Cinek animator.setInterpolator(properties.interpolator); 1304c6969a512cd70831249ec1d07691f16fe5465f5Selim Cinek } 1314c6969a512cd70831249ec1d07691f16fe5465f5Selim Cinek 1324c6969a512cd70831249ec1d07691f16fe5465f5Selim Cinek private AnimatorProperties getProperties(float currValue, 1334c6969a512cd70831249ec1d07691f16fe5465f5Selim Cinek float endValue, float velocity, float maxDistance) { 1341d480695df31f1c328473f32d5007cea6a03b6e0Jorim Jaggi float maxLengthSeconds = (float) (mMaxLengthSeconds 1351d480695df31f1c328473f32d5007cea6a03b6e0Jorim Jaggi * Math.sqrt(Math.abs(endValue - currValue) / maxDistance)); 13687cd5e71ec087e191b8baaa8913a878f92d4e10dJorim Jaggi float diff = Math.abs(endValue - currValue); 13787cd5e71ec087e191b8baaa8913a878f92d4e10dJorim Jaggi float velAbs = Math.abs(velocity); 13887cd5e71ec087e191b8baaa8913a878f92d4e10dJorim Jaggi float durationSeconds = LINEAR_OUT_SLOW_IN_START_GRADIENT * diff / velAbs; 1391d480695df31f1c328473f32d5007cea6a03b6e0Jorim Jaggi if (durationSeconds <= maxLengthSeconds) { 1404c6969a512cd70831249ec1d07691f16fe5465f5Selim Cinek mAnimatorProperties.interpolator = mLinearOutSlowIn; 14187cd5e71ec087e191b8baaa8913a878f92d4e10dJorim Jaggi } else if (velAbs >= mMinVelocityPxPerSecond) { 14287cd5e71ec087e191b8baaa8913a878f92d4e10dJorim Jaggi 14387cd5e71ec087e191b8baaa8913a878f92d4e10dJorim Jaggi // Cross fade between fast-out-slow-in and linear interpolator with current velocity. 1441d480695df31f1c328473f32d5007cea6a03b6e0Jorim Jaggi durationSeconds = maxLengthSeconds; 14587cd5e71ec087e191b8baaa8913a878f92d4e10dJorim Jaggi VelocityInterpolator velocityInterpolator 14687cd5e71ec087e191b8baaa8913a878f92d4e10dJorim Jaggi = new VelocityInterpolator(durationSeconds, velAbs, diff); 14787cd5e71ec087e191b8baaa8913a878f92d4e10dJorim Jaggi InterpolatorInterpolator superInterpolator = new InterpolatorInterpolator( 14887cd5e71ec087e191b8baaa8913a878f92d4e10dJorim Jaggi velocityInterpolator, mLinearOutSlowIn, mLinearOutSlowIn); 1494c6969a512cd70831249ec1d07691f16fe5465f5Selim Cinek mAnimatorProperties.interpolator = superInterpolator; 15087cd5e71ec087e191b8baaa8913a878f92d4e10dJorim Jaggi } else { 15187cd5e71ec087e191b8baaa8913a878f92d4e10dJorim Jaggi 15287cd5e71ec087e191b8baaa8913a878f92d4e10dJorim Jaggi // Just use a normal interpolator which doesn't take the velocity into account. 1531d480695df31f1c328473f32d5007cea6a03b6e0Jorim Jaggi durationSeconds = maxLengthSeconds; 1544c6969a512cd70831249ec1d07691f16fe5465f5Selim Cinek mAnimatorProperties.interpolator = mFastOutSlowIn; 15587cd5e71ec087e191b8baaa8913a878f92d4e10dJorim Jaggi } 1564c6969a512cd70831249ec1d07691f16fe5465f5Selim Cinek mAnimatorProperties.duration = (long) (durationSeconds * 1000); 1574c6969a512cd70831249ec1d07691f16fe5465f5Selim Cinek return mAnimatorProperties; 15887cd5e71ec087e191b8baaa8913a878f92d4e10dJorim Jaggi } 15987cd5e71ec087e191b8baaa8913a878f92d4e10dJorim Jaggi 16087cd5e71ec087e191b8baaa8913a878f92d4e10dJorim Jaggi /** 1611d480695df31f1c328473f32d5007cea6a03b6e0Jorim Jaggi * Applies the interpolator and length to the animator, such that the fling animation is 1621d480695df31f1c328473f32d5007cea6a03b6e0Jorim Jaggi * consistent with the finger motion for the case when the animation is making something 1631d480695df31f1c328473f32d5007cea6a03b6e0Jorim Jaggi * disappear. 1641d480695df31f1c328473f32d5007cea6a03b6e0Jorim Jaggi * 1651d480695df31f1c328473f32d5007cea6a03b6e0Jorim Jaggi * @param animator the animator to apply 1661d480695df31f1c328473f32d5007cea6a03b6e0Jorim Jaggi * @param currValue the current value 1671d480695df31f1c328473f32d5007cea6a03b6e0Jorim Jaggi * @param endValue the end value of the animator 1681d480695df31f1c328473f32d5007cea6a03b6e0Jorim Jaggi * @param velocity the current velocity of the motion 1691d480695df31f1c328473f32d5007cea6a03b6e0Jorim Jaggi * @param maxDistance the maximum distance for this interaction; the maximum animation length 1701d480695df31f1c328473f32d5007cea6a03b6e0Jorim Jaggi * gets multiplied by the ratio between the actual distance and this value 1711d480695df31f1c328473f32d5007cea6a03b6e0Jorim Jaggi */ 172b6cdcbc66b4b862f83afde85b8e7109b6450b15eJorim Jaggi public void applyDismissing(Animator animator, float currValue, float endValue, 1731d480695df31f1c328473f32d5007cea6a03b6e0Jorim Jaggi float velocity, float maxDistance) { 1744c6969a512cd70831249ec1d07691f16fe5465f5Selim Cinek AnimatorProperties properties = getDismissingProperties(currValue, endValue, velocity, 1754c6969a512cd70831249ec1d07691f16fe5465f5Selim Cinek maxDistance); 1764c6969a512cd70831249ec1d07691f16fe5465f5Selim Cinek animator.setDuration(properties.duration); 1774c6969a512cd70831249ec1d07691f16fe5465f5Selim Cinek animator.setInterpolator(properties.interpolator); 1784c6969a512cd70831249ec1d07691f16fe5465f5Selim Cinek } 1794c6969a512cd70831249ec1d07691f16fe5465f5Selim Cinek 1804c6969a512cd70831249ec1d07691f16fe5465f5Selim Cinek /** 1814c6969a512cd70831249ec1d07691f16fe5465f5Selim Cinek * Applies the interpolator and length to the animator, such that the fling animation is 1824c6969a512cd70831249ec1d07691f16fe5465f5Selim Cinek * consistent with the finger motion for the case when the animation is making something 1834c6969a512cd70831249ec1d07691f16fe5465f5Selim Cinek * disappear. 1844c6969a512cd70831249ec1d07691f16fe5465f5Selim Cinek * 1854c6969a512cd70831249ec1d07691f16fe5465f5Selim Cinek * @param animator the animator to apply 1864c6969a512cd70831249ec1d07691f16fe5465f5Selim Cinek * @param currValue the current value 1874c6969a512cd70831249ec1d07691f16fe5465f5Selim Cinek * @param endValue the end value of the animator 1884c6969a512cd70831249ec1d07691f16fe5465f5Selim Cinek * @param velocity the current velocity of the motion 1894c6969a512cd70831249ec1d07691f16fe5465f5Selim Cinek * @param maxDistance the maximum distance for this interaction; the maximum animation length 1904c6969a512cd70831249ec1d07691f16fe5465f5Selim Cinek * gets multiplied by the ratio between the actual distance and this value 1914c6969a512cd70831249ec1d07691f16fe5465f5Selim Cinek */ 1924c6969a512cd70831249ec1d07691f16fe5465f5Selim Cinek public void applyDismissing(ViewPropertyAnimator animator, float currValue, float endValue, 1934c6969a512cd70831249ec1d07691f16fe5465f5Selim Cinek float velocity, float maxDistance) { 1944c6969a512cd70831249ec1d07691f16fe5465f5Selim Cinek AnimatorProperties properties = getDismissingProperties(currValue, endValue, velocity, 1954c6969a512cd70831249ec1d07691f16fe5465f5Selim Cinek maxDistance); 1964c6969a512cd70831249ec1d07691f16fe5465f5Selim Cinek animator.setDuration(properties.duration); 1974c6969a512cd70831249ec1d07691f16fe5465f5Selim Cinek animator.setInterpolator(properties.interpolator); 1984c6969a512cd70831249ec1d07691f16fe5465f5Selim Cinek } 1994c6969a512cd70831249ec1d07691f16fe5465f5Selim Cinek 2004c6969a512cd70831249ec1d07691f16fe5465f5Selim Cinek private AnimatorProperties getDismissingProperties(float currValue, float endValue, 2014c6969a512cd70831249ec1d07691f16fe5465f5Selim Cinek float velocity, float maxDistance) { 2021d480695df31f1c328473f32d5007cea6a03b6e0Jorim Jaggi float maxLengthSeconds = (float) (mMaxLengthSeconds 2031d480695df31f1c328473f32d5007cea6a03b6e0Jorim Jaggi * Math.pow(Math.abs(endValue - currValue) / maxDistance, 0.5f)); 2041d480695df31f1c328473f32d5007cea6a03b6e0Jorim Jaggi float diff = Math.abs(endValue - currValue); 2051d480695df31f1c328473f32d5007cea6a03b6e0Jorim Jaggi float velAbs = Math.abs(velocity); 206efbd7e3bb8244efae2561f0d9d7cedb36b1730bdJorim Jaggi float y2 = calculateLinearOutFasterInY2(velAbs); 207efbd7e3bb8244efae2561f0d9d7cedb36b1730bdJorim Jaggi 2082580a976ec93a01ed00fae51364ad872bc591d95Jorim Jaggi float startGradient = y2 / LINEAR_OUT_FASTER_IN_X2; 2092580a976ec93a01ed00fae51364ad872bc591d95Jorim Jaggi Interpolator mLinearOutFasterIn = new PathInterpolator(0, 0, LINEAR_OUT_FASTER_IN_X2, y2); 210efbd7e3bb8244efae2561f0d9d7cedb36b1730bdJorim Jaggi float durationSeconds = startGradient * diff / velAbs; 2111d480695df31f1c328473f32d5007cea6a03b6e0Jorim Jaggi if (durationSeconds <= maxLengthSeconds) { 2124c6969a512cd70831249ec1d07691f16fe5465f5Selim Cinek mAnimatorProperties.interpolator = mLinearOutFasterIn; 2131d480695df31f1c328473f32d5007cea6a03b6e0Jorim Jaggi } else if (velAbs >= mMinVelocityPxPerSecond) { 2141d480695df31f1c328473f32d5007cea6a03b6e0Jorim Jaggi 2151d480695df31f1c328473f32d5007cea6a03b6e0Jorim Jaggi // Cross fade between linear-out-faster-in and linear interpolator with current 2161d480695df31f1c328473f32d5007cea6a03b6e0Jorim Jaggi // velocity. 2171d480695df31f1c328473f32d5007cea6a03b6e0Jorim Jaggi durationSeconds = maxLengthSeconds; 2181d480695df31f1c328473f32d5007cea6a03b6e0Jorim Jaggi VelocityInterpolator velocityInterpolator 2191d480695df31f1c328473f32d5007cea6a03b6e0Jorim Jaggi = new VelocityInterpolator(durationSeconds, velAbs, diff); 2201d480695df31f1c328473f32d5007cea6a03b6e0Jorim Jaggi InterpolatorInterpolator superInterpolator = new InterpolatorInterpolator( 2211d480695df31f1c328473f32d5007cea6a03b6e0Jorim Jaggi velocityInterpolator, mLinearOutFasterIn, mLinearOutSlowIn); 2224c6969a512cd70831249ec1d07691f16fe5465f5Selim Cinek mAnimatorProperties.interpolator = superInterpolator; 2231d480695df31f1c328473f32d5007cea6a03b6e0Jorim Jaggi } else { 2241d480695df31f1c328473f32d5007cea6a03b6e0Jorim Jaggi 2251d480695df31f1c328473f32d5007cea6a03b6e0Jorim Jaggi // Just use a normal interpolator which doesn't take the velocity into account. 2261d480695df31f1c328473f32d5007cea6a03b6e0Jorim Jaggi durationSeconds = maxLengthSeconds; 2274c6969a512cd70831249ec1d07691f16fe5465f5Selim Cinek mAnimatorProperties.interpolator = mFastOutLinearIn; 2281d480695df31f1c328473f32d5007cea6a03b6e0Jorim Jaggi } 2294c6969a512cd70831249ec1d07691f16fe5465f5Selim Cinek mAnimatorProperties.duration = (long) (durationSeconds * 1000); 2304c6969a512cd70831249ec1d07691f16fe5465f5Selim Cinek return mAnimatorProperties; 2311d480695df31f1c328473f32d5007cea6a03b6e0Jorim Jaggi } 2321d480695df31f1c328473f32d5007cea6a03b6e0Jorim Jaggi 2331d480695df31f1c328473f32d5007cea6a03b6e0Jorim Jaggi /** 234efbd7e3bb8244efae2561f0d9d7cedb36b1730bdJorim Jaggi * Calculates the y2 control point for a linear-out-faster-in path interpolator depending on the 235efbd7e3bb8244efae2561f0d9d7cedb36b1730bdJorim Jaggi * velocity. The faster the velocity, the more "linear" the interpolator gets. 236efbd7e3bb8244efae2561f0d9d7cedb36b1730bdJorim Jaggi * 237efbd7e3bb8244efae2561f0d9d7cedb36b1730bdJorim Jaggi * @param velocity the velocity of the gesture. 238efbd7e3bb8244efae2561f0d9d7cedb36b1730bdJorim Jaggi * @return the y2 control point for a cubic bezier path interpolator 239efbd7e3bb8244efae2561f0d9d7cedb36b1730bdJorim Jaggi */ 240efbd7e3bb8244efae2561f0d9d7cedb36b1730bdJorim Jaggi private float calculateLinearOutFasterInY2(float velocity) { 241efbd7e3bb8244efae2561f0d9d7cedb36b1730bdJorim Jaggi float t = (velocity - mMinVelocityPxPerSecond) 242efbd7e3bb8244efae2561f0d9d7cedb36b1730bdJorim Jaggi / (mHighVelocityPxPerSecond - mMinVelocityPxPerSecond); 243efbd7e3bb8244efae2561f0d9d7cedb36b1730bdJorim Jaggi t = Math.max(0, Math.min(1, t)); 244efbd7e3bb8244efae2561f0d9d7cedb36b1730bdJorim Jaggi return (1 - t) * LINEAR_OUT_FASTER_IN_Y2_MIN + t * LINEAR_OUT_FASTER_IN_Y2_MAX; 245efbd7e3bb8244efae2561f0d9d7cedb36b1730bdJorim Jaggi } 246efbd7e3bb8244efae2561f0d9d7cedb36b1730bdJorim Jaggi 247efbd7e3bb8244efae2561f0d9d7cedb36b1730bdJorim Jaggi /** 2481d480695df31f1c328473f32d5007cea6a03b6e0Jorim Jaggi * @return the minimum velocity a gesture needs to have to be considered a fling 2491d480695df31f1c328473f32d5007cea6a03b6e0Jorim Jaggi */ 2501d480695df31f1c328473f32d5007cea6a03b6e0Jorim Jaggi public float getMinVelocityPxPerSecond() { 2511d480695df31f1c328473f32d5007cea6a03b6e0Jorim Jaggi return mMinVelocityPxPerSecond; 2521d480695df31f1c328473f32d5007cea6a03b6e0Jorim Jaggi } 2531d480695df31f1c328473f32d5007cea6a03b6e0Jorim Jaggi 2541d480695df31f1c328473f32d5007cea6a03b6e0Jorim Jaggi /** 25587cd5e71ec087e191b8baaa8913a878f92d4e10dJorim Jaggi * An interpolator which interpolates two interpolators with an interpolator. 25687cd5e71ec087e191b8baaa8913a878f92d4e10dJorim Jaggi */ 25787cd5e71ec087e191b8baaa8913a878f92d4e10dJorim Jaggi private static final class InterpolatorInterpolator implements Interpolator { 25887cd5e71ec087e191b8baaa8913a878f92d4e10dJorim Jaggi 25987cd5e71ec087e191b8baaa8913a878f92d4e10dJorim Jaggi private Interpolator mInterpolator1; 26087cd5e71ec087e191b8baaa8913a878f92d4e10dJorim Jaggi private Interpolator mInterpolator2; 26187cd5e71ec087e191b8baaa8913a878f92d4e10dJorim Jaggi private Interpolator mCrossfader; 26287cd5e71ec087e191b8baaa8913a878f92d4e10dJorim Jaggi 26387cd5e71ec087e191b8baaa8913a878f92d4e10dJorim Jaggi InterpolatorInterpolator(Interpolator interpolator1, Interpolator interpolator2, 26487cd5e71ec087e191b8baaa8913a878f92d4e10dJorim Jaggi Interpolator crossfader) { 26587cd5e71ec087e191b8baaa8913a878f92d4e10dJorim Jaggi mInterpolator1 = interpolator1; 26687cd5e71ec087e191b8baaa8913a878f92d4e10dJorim Jaggi mInterpolator2 = interpolator2; 26787cd5e71ec087e191b8baaa8913a878f92d4e10dJorim Jaggi mCrossfader = crossfader; 26887cd5e71ec087e191b8baaa8913a878f92d4e10dJorim Jaggi } 26987cd5e71ec087e191b8baaa8913a878f92d4e10dJorim Jaggi 27087cd5e71ec087e191b8baaa8913a878f92d4e10dJorim Jaggi @Override 27187cd5e71ec087e191b8baaa8913a878f92d4e10dJorim Jaggi public float getInterpolation(float input) { 27287cd5e71ec087e191b8baaa8913a878f92d4e10dJorim Jaggi float t = mCrossfader.getInterpolation(input); 27387cd5e71ec087e191b8baaa8913a878f92d4e10dJorim Jaggi return (1 - t) * mInterpolator1.getInterpolation(input) 27487cd5e71ec087e191b8baaa8913a878f92d4e10dJorim Jaggi + t * mInterpolator2.getInterpolation(input); 27587cd5e71ec087e191b8baaa8913a878f92d4e10dJorim Jaggi } 27687cd5e71ec087e191b8baaa8913a878f92d4e10dJorim Jaggi } 27787cd5e71ec087e191b8baaa8913a878f92d4e10dJorim Jaggi 27887cd5e71ec087e191b8baaa8913a878f92d4e10dJorim Jaggi /** 27987cd5e71ec087e191b8baaa8913a878f92d4e10dJorim Jaggi * An interpolator which interpolates with a fixed velocity. 28087cd5e71ec087e191b8baaa8913a878f92d4e10dJorim Jaggi */ 28187cd5e71ec087e191b8baaa8913a878f92d4e10dJorim Jaggi private static final class VelocityInterpolator implements Interpolator { 28287cd5e71ec087e191b8baaa8913a878f92d4e10dJorim Jaggi 28387cd5e71ec087e191b8baaa8913a878f92d4e10dJorim Jaggi private float mDurationSeconds; 28487cd5e71ec087e191b8baaa8913a878f92d4e10dJorim Jaggi private float mVelocity; 28587cd5e71ec087e191b8baaa8913a878f92d4e10dJorim Jaggi private float mDiff; 28687cd5e71ec087e191b8baaa8913a878f92d4e10dJorim Jaggi 28787cd5e71ec087e191b8baaa8913a878f92d4e10dJorim Jaggi private VelocityInterpolator(float durationSeconds, float velocity, float diff) { 28887cd5e71ec087e191b8baaa8913a878f92d4e10dJorim Jaggi mDurationSeconds = durationSeconds; 28987cd5e71ec087e191b8baaa8913a878f92d4e10dJorim Jaggi mVelocity = velocity; 29087cd5e71ec087e191b8baaa8913a878f92d4e10dJorim Jaggi mDiff = diff; 29187cd5e71ec087e191b8baaa8913a878f92d4e10dJorim Jaggi } 29287cd5e71ec087e191b8baaa8913a878f92d4e10dJorim Jaggi 29387cd5e71ec087e191b8baaa8913a878f92d4e10dJorim Jaggi @Override 29487cd5e71ec087e191b8baaa8913a878f92d4e10dJorim Jaggi public float getInterpolation(float input) { 29587cd5e71ec087e191b8baaa8913a878f92d4e10dJorim Jaggi float time = input * mDurationSeconds; 29687cd5e71ec087e191b8baaa8913a878f92d4e10dJorim Jaggi return time * mVelocity / mDiff; 29787cd5e71ec087e191b8baaa8913a878f92d4e10dJorim Jaggi } 29887cd5e71ec087e191b8baaa8913a878f92d4e10dJorim Jaggi } 2994c6969a512cd70831249ec1d07691f16fe5465f5Selim Cinek 3004c6969a512cd70831249ec1d07691f16fe5465f5Selim Cinek private static class AnimatorProperties { 3014c6969a512cd70831249ec1d07691f16fe5465f5Selim Cinek Interpolator interpolator; 3024c6969a512cd70831249ec1d07691f16fe5465f5Selim Cinek long duration; 3034c6969a512cd70831249ec1d07691f16fe5465f5Selim Cinek } 3044c6969a512cd70831249ec1d07691f16fe5465f5Selim Cinek 30587cd5e71ec087e191b8baaa8913a878f92d4e10dJorim Jaggi} 306