FlingAnimationUtils.java revision c0d7058b14c24cd07912f5629c26b39b7b4673d5
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.content.Context; 214c6969a512cd70831249ec1d07691f16fe5465f5Selim Cinekimport android.view.ViewPropertyAnimator; 2287cd5e71ec087e191b8baaa8913a878f92d4e10dJorim Jaggiimport android.view.animation.Interpolator; 2387cd5e71ec087e191b8baaa8913a878f92d4e10dJorim Jaggiimport android.view.animation.PathInterpolator; 2487cd5e71ec087e191b8baaa8913a878f92d4e10dJorim Jaggi 25c0d7058b14c24cd07912f5629c26b39b7b4673d5Winsonimport com.android.systemui.Interpolators; 26c0d7058b14c24cd07912f5629c26b39b7b4673d5Winson 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; 451d480695df31f1c328473f32d5007cea6a03b6e0Jorim Jaggi 4687cd5e71ec087e191b8baaa8913a878f92d4e10dJorim Jaggi private float mMinVelocityPxPerSecond; 471d480695df31f1c328473f32d5007cea6a03b6e0Jorim Jaggi private float mMaxLengthSeconds; 48efbd7e3bb8244efae2561f0d9d7cedb36b1730bdJorim Jaggi private float mHighVelocityPxPerSecond; 4987cd5e71ec087e191b8baaa8913a878f92d4e10dJorim Jaggi 504c6969a512cd70831249ec1d07691f16fe5465f5Selim Cinek private AnimatorProperties mAnimatorProperties = new AnimatorProperties(); 514c6969a512cd70831249ec1d07691f16fe5465f5Selim Cinek 521d480695df31f1c328473f32d5007cea6a03b6e0Jorim Jaggi public FlingAnimationUtils(Context ctx, float maxLengthSeconds) { 531d480695df31f1c328473f32d5007cea6a03b6e0Jorim Jaggi mMaxLengthSeconds = maxLengthSeconds; 541d480695df31f1c328473f32d5007cea6a03b6e0Jorim Jaggi mLinearOutSlowIn = new PathInterpolator(0, 0, LINEAR_OUT_SLOW_IN_X2, 1); 5587cd5e71ec087e191b8baaa8913a878f92d4e10dJorim Jaggi mMinVelocityPxPerSecond 5687cd5e71ec087e191b8baaa8913a878f92d4e10dJorim Jaggi = MIN_VELOCITY_DP_PER_SECOND * ctx.getResources().getDisplayMetrics().density; 57efbd7e3bb8244efae2561f0d9d7cedb36b1730bdJorim Jaggi mHighVelocityPxPerSecond 58efbd7e3bb8244efae2561f0d9d7cedb36b1730bdJorim Jaggi = HIGH_VELOCITY_DP_PER_SECOND * ctx.getResources().getDisplayMetrics().density; 5987cd5e71ec087e191b8baaa8913a878f92d4e10dJorim Jaggi } 6087cd5e71ec087e191b8baaa8913a878f92d4e10dJorim Jaggi 6187cd5e71ec087e191b8baaa8913a878f92d4e10dJorim Jaggi /** 6287cd5e71ec087e191b8baaa8913a878f92d4e10dJorim Jaggi * Applies the interpolator and length to the animator, such that the fling animation is 6387cd5e71ec087e191b8baaa8913a878f92d4e10dJorim Jaggi * consistent with the finger motion. 6487cd5e71ec087e191b8baaa8913a878f92d4e10dJorim Jaggi * 6587cd5e71ec087e191b8baaa8913a878f92d4e10dJorim Jaggi * @param animator the animator to apply 6687cd5e71ec087e191b8baaa8913a878f92d4e10dJorim Jaggi * @param currValue the current value 6787cd5e71ec087e191b8baaa8913a878f92d4e10dJorim Jaggi * @param endValue the end value of the animator 6887cd5e71ec087e191b8baaa8913a878f92d4e10dJorim Jaggi * @param velocity the current velocity of the motion 6987cd5e71ec087e191b8baaa8913a878f92d4e10dJorim Jaggi */ 70b6cdcbc66b4b862f83afde85b8e7109b6450b15eJorim Jaggi public void apply(Animator animator, float currValue, float endValue, float velocity) { 711d480695df31f1c328473f32d5007cea6a03b6e0Jorim Jaggi apply(animator, currValue, endValue, velocity, Math.abs(endValue - currValue)); 721d480695df31f1c328473f32d5007cea6a03b6e0Jorim Jaggi } 731d480695df31f1c328473f32d5007cea6a03b6e0Jorim Jaggi 741d480695df31f1c328473f32d5007cea6a03b6e0Jorim Jaggi /** 751d480695df31f1c328473f32d5007cea6a03b6e0Jorim Jaggi * Applies the interpolator and length to the animator, such that the fling animation is 761d480695df31f1c328473f32d5007cea6a03b6e0Jorim Jaggi * consistent with the finger motion. 771d480695df31f1c328473f32d5007cea6a03b6e0Jorim Jaggi * 781d480695df31f1c328473f32d5007cea6a03b6e0Jorim Jaggi * @param animator the animator to apply 791d480695df31f1c328473f32d5007cea6a03b6e0Jorim Jaggi * @param currValue the current value 801d480695df31f1c328473f32d5007cea6a03b6e0Jorim Jaggi * @param endValue the end value of the animator 811d480695df31f1c328473f32d5007cea6a03b6e0Jorim Jaggi * @param velocity the current velocity of the motion 824c6969a512cd70831249ec1d07691f16fe5465f5Selim Cinek */ 834c6969a512cd70831249ec1d07691f16fe5465f5Selim Cinek public void apply(ViewPropertyAnimator animator, float currValue, float endValue, 844c6969a512cd70831249ec1d07691f16fe5465f5Selim Cinek float velocity) { 854c6969a512cd70831249ec1d07691f16fe5465f5Selim Cinek apply(animator, currValue, endValue, velocity, Math.abs(endValue - currValue)); 864c6969a512cd70831249ec1d07691f16fe5465f5Selim Cinek } 874c6969a512cd70831249ec1d07691f16fe5465f5Selim Cinek 884c6969a512cd70831249ec1d07691f16fe5465f5Selim Cinek /** 894c6969a512cd70831249ec1d07691f16fe5465f5Selim Cinek * Applies the interpolator and length to the animator, such that the fling animation is 904c6969a512cd70831249ec1d07691f16fe5465f5Selim Cinek * consistent with the finger motion. 914c6969a512cd70831249ec1d07691f16fe5465f5Selim Cinek * 924c6969a512cd70831249ec1d07691f16fe5465f5Selim Cinek * @param animator the animator to apply 934c6969a512cd70831249ec1d07691f16fe5465f5Selim Cinek * @param currValue the current value 944c6969a512cd70831249ec1d07691f16fe5465f5Selim Cinek * @param endValue the end value of the animator 954c6969a512cd70831249ec1d07691f16fe5465f5Selim Cinek * @param velocity the current velocity of the motion 961d480695df31f1c328473f32d5007cea6a03b6e0Jorim Jaggi * @param maxDistance the maximum distance for this interaction; the maximum animation length 971d480695df31f1c328473f32d5007cea6a03b6e0Jorim Jaggi * gets multiplied by the ratio between the actual distance and this value 981d480695df31f1c328473f32d5007cea6a03b6e0Jorim Jaggi */ 99b6cdcbc66b4b862f83afde85b8e7109b6450b15eJorim Jaggi public void apply(Animator animator, float currValue, float endValue, float velocity, 1001d480695df31f1c328473f32d5007cea6a03b6e0Jorim Jaggi float maxDistance) { 1014c6969a512cd70831249ec1d07691f16fe5465f5Selim Cinek AnimatorProperties properties = getProperties(currValue, endValue, velocity, 1024c6969a512cd70831249ec1d07691f16fe5465f5Selim Cinek maxDistance); 1034c6969a512cd70831249ec1d07691f16fe5465f5Selim Cinek animator.setDuration(properties.duration); 1044c6969a512cd70831249ec1d07691f16fe5465f5Selim Cinek animator.setInterpolator(properties.interpolator); 1054c6969a512cd70831249ec1d07691f16fe5465f5Selim Cinek } 1064c6969a512cd70831249ec1d07691f16fe5465f5Selim Cinek 1074c6969a512cd70831249ec1d07691f16fe5465f5Selim Cinek /** 1084c6969a512cd70831249ec1d07691f16fe5465f5Selim Cinek * Applies the interpolator and length to the animator, such that the fling animation is 1094c6969a512cd70831249ec1d07691f16fe5465f5Selim Cinek * consistent with the finger motion. 1104c6969a512cd70831249ec1d07691f16fe5465f5Selim Cinek * 1114c6969a512cd70831249ec1d07691f16fe5465f5Selim Cinek * @param animator the animator to apply 1124c6969a512cd70831249ec1d07691f16fe5465f5Selim Cinek * @param currValue the current value 1134c6969a512cd70831249ec1d07691f16fe5465f5Selim Cinek * @param endValue the end value of the animator 1144c6969a512cd70831249ec1d07691f16fe5465f5Selim Cinek * @param velocity the current velocity of the motion 1154c6969a512cd70831249ec1d07691f16fe5465f5Selim Cinek * @param maxDistance the maximum distance for this interaction; the maximum animation length 1164c6969a512cd70831249ec1d07691f16fe5465f5Selim Cinek * gets multiplied by the ratio between the actual distance and this value 1174c6969a512cd70831249ec1d07691f16fe5465f5Selim Cinek */ 1184c6969a512cd70831249ec1d07691f16fe5465f5Selim Cinek public void apply(ViewPropertyAnimator animator, float currValue, float endValue, 1194c6969a512cd70831249ec1d07691f16fe5465f5Selim Cinek float velocity, float maxDistance) { 1204c6969a512cd70831249ec1d07691f16fe5465f5Selim Cinek AnimatorProperties properties = getProperties(currValue, endValue, velocity, 1214c6969a512cd70831249ec1d07691f16fe5465f5Selim Cinek maxDistance); 1224c6969a512cd70831249ec1d07691f16fe5465f5Selim Cinek animator.setDuration(properties.duration); 1234c6969a512cd70831249ec1d07691f16fe5465f5Selim Cinek animator.setInterpolator(properties.interpolator); 1244c6969a512cd70831249ec1d07691f16fe5465f5Selim Cinek } 1254c6969a512cd70831249ec1d07691f16fe5465f5Selim Cinek 1264c6969a512cd70831249ec1d07691f16fe5465f5Selim Cinek private AnimatorProperties getProperties(float currValue, 1274c6969a512cd70831249ec1d07691f16fe5465f5Selim Cinek float endValue, float velocity, float maxDistance) { 1281d480695df31f1c328473f32d5007cea6a03b6e0Jorim Jaggi float maxLengthSeconds = (float) (mMaxLengthSeconds 1291d480695df31f1c328473f32d5007cea6a03b6e0Jorim Jaggi * Math.sqrt(Math.abs(endValue - currValue) / maxDistance)); 13087cd5e71ec087e191b8baaa8913a878f92d4e10dJorim Jaggi float diff = Math.abs(endValue - currValue); 13187cd5e71ec087e191b8baaa8913a878f92d4e10dJorim Jaggi float velAbs = Math.abs(velocity); 13287cd5e71ec087e191b8baaa8913a878f92d4e10dJorim Jaggi float durationSeconds = LINEAR_OUT_SLOW_IN_START_GRADIENT * diff / velAbs; 1331d480695df31f1c328473f32d5007cea6a03b6e0Jorim Jaggi if (durationSeconds <= maxLengthSeconds) { 1344c6969a512cd70831249ec1d07691f16fe5465f5Selim Cinek mAnimatorProperties.interpolator = mLinearOutSlowIn; 13587cd5e71ec087e191b8baaa8913a878f92d4e10dJorim Jaggi } else if (velAbs >= mMinVelocityPxPerSecond) { 13687cd5e71ec087e191b8baaa8913a878f92d4e10dJorim Jaggi 13787cd5e71ec087e191b8baaa8913a878f92d4e10dJorim Jaggi // Cross fade between fast-out-slow-in and linear interpolator with current velocity. 1381d480695df31f1c328473f32d5007cea6a03b6e0Jorim Jaggi durationSeconds = maxLengthSeconds; 13987cd5e71ec087e191b8baaa8913a878f92d4e10dJorim Jaggi VelocityInterpolator velocityInterpolator 14087cd5e71ec087e191b8baaa8913a878f92d4e10dJorim Jaggi = new VelocityInterpolator(durationSeconds, velAbs, diff); 14187cd5e71ec087e191b8baaa8913a878f92d4e10dJorim Jaggi InterpolatorInterpolator superInterpolator = new InterpolatorInterpolator( 14287cd5e71ec087e191b8baaa8913a878f92d4e10dJorim Jaggi velocityInterpolator, mLinearOutSlowIn, mLinearOutSlowIn); 1434c6969a512cd70831249ec1d07691f16fe5465f5Selim Cinek mAnimatorProperties.interpolator = superInterpolator; 14487cd5e71ec087e191b8baaa8913a878f92d4e10dJorim Jaggi } else { 14587cd5e71ec087e191b8baaa8913a878f92d4e10dJorim Jaggi 14687cd5e71ec087e191b8baaa8913a878f92d4e10dJorim Jaggi // Just use a normal interpolator which doesn't take the velocity into account. 1471d480695df31f1c328473f32d5007cea6a03b6e0Jorim Jaggi durationSeconds = maxLengthSeconds; 148c18010f6720f606003cde3cd376ddacaca30f6e5Selim Cinek mAnimatorProperties.interpolator = Interpolators.FAST_OUT_SLOW_IN; 14987cd5e71ec087e191b8baaa8913a878f92d4e10dJorim Jaggi } 1504c6969a512cd70831249ec1d07691f16fe5465f5Selim Cinek mAnimatorProperties.duration = (long) (durationSeconds * 1000); 1514c6969a512cd70831249ec1d07691f16fe5465f5Selim Cinek return mAnimatorProperties; 15287cd5e71ec087e191b8baaa8913a878f92d4e10dJorim Jaggi } 15387cd5e71ec087e191b8baaa8913a878f92d4e10dJorim Jaggi 15487cd5e71ec087e191b8baaa8913a878f92d4e10dJorim Jaggi /** 1551d480695df31f1c328473f32d5007cea6a03b6e0Jorim Jaggi * Applies the interpolator and length to the animator, such that the fling animation is 1561d480695df31f1c328473f32d5007cea6a03b6e0Jorim Jaggi * consistent with the finger motion for the case when the animation is making something 1571d480695df31f1c328473f32d5007cea6a03b6e0Jorim Jaggi * disappear. 1581d480695df31f1c328473f32d5007cea6a03b6e0Jorim Jaggi * 1591d480695df31f1c328473f32d5007cea6a03b6e0Jorim Jaggi * @param animator the animator to apply 1601d480695df31f1c328473f32d5007cea6a03b6e0Jorim Jaggi * @param currValue the current value 1611d480695df31f1c328473f32d5007cea6a03b6e0Jorim Jaggi * @param endValue the end value of the animator 1621d480695df31f1c328473f32d5007cea6a03b6e0Jorim Jaggi * @param velocity the current velocity of the motion 1631d480695df31f1c328473f32d5007cea6a03b6e0Jorim Jaggi * @param maxDistance the maximum distance for this interaction; the maximum animation length 1641d480695df31f1c328473f32d5007cea6a03b6e0Jorim Jaggi * gets multiplied by the ratio between the actual distance and this value 1651d480695df31f1c328473f32d5007cea6a03b6e0Jorim Jaggi */ 166b6cdcbc66b4b862f83afde85b8e7109b6450b15eJorim Jaggi public void applyDismissing(Animator animator, float currValue, float endValue, 1671d480695df31f1c328473f32d5007cea6a03b6e0Jorim Jaggi float velocity, float maxDistance) { 1684c6969a512cd70831249ec1d07691f16fe5465f5Selim Cinek AnimatorProperties properties = getDismissingProperties(currValue, endValue, velocity, 1694c6969a512cd70831249ec1d07691f16fe5465f5Selim Cinek maxDistance); 1704c6969a512cd70831249ec1d07691f16fe5465f5Selim Cinek animator.setDuration(properties.duration); 1714c6969a512cd70831249ec1d07691f16fe5465f5Selim Cinek animator.setInterpolator(properties.interpolator); 1724c6969a512cd70831249ec1d07691f16fe5465f5Selim Cinek } 1734c6969a512cd70831249ec1d07691f16fe5465f5Selim Cinek 1744c6969a512cd70831249ec1d07691f16fe5465f5Selim Cinek /** 1754c6969a512cd70831249ec1d07691f16fe5465f5Selim Cinek * Applies the interpolator and length to the animator, such that the fling animation is 1764c6969a512cd70831249ec1d07691f16fe5465f5Selim Cinek * consistent with the finger motion for the case when the animation is making something 1774c6969a512cd70831249ec1d07691f16fe5465f5Selim Cinek * disappear. 1784c6969a512cd70831249ec1d07691f16fe5465f5Selim Cinek * 1794c6969a512cd70831249ec1d07691f16fe5465f5Selim Cinek * @param animator the animator to apply 1804c6969a512cd70831249ec1d07691f16fe5465f5Selim Cinek * @param currValue the current value 1814c6969a512cd70831249ec1d07691f16fe5465f5Selim Cinek * @param endValue the end value of the animator 1824c6969a512cd70831249ec1d07691f16fe5465f5Selim Cinek * @param velocity the current velocity of the motion 1834c6969a512cd70831249ec1d07691f16fe5465f5Selim Cinek * @param maxDistance the maximum distance for this interaction; the maximum animation length 1844c6969a512cd70831249ec1d07691f16fe5465f5Selim Cinek * gets multiplied by the ratio between the actual distance and this value 1854c6969a512cd70831249ec1d07691f16fe5465f5Selim Cinek */ 1864c6969a512cd70831249ec1d07691f16fe5465f5Selim Cinek public void applyDismissing(ViewPropertyAnimator animator, float currValue, float endValue, 1874c6969a512cd70831249ec1d07691f16fe5465f5Selim Cinek float velocity, float maxDistance) { 1884c6969a512cd70831249ec1d07691f16fe5465f5Selim Cinek AnimatorProperties properties = getDismissingProperties(currValue, endValue, velocity, 1894c6969a512cd70831249ec1d07691f16fe5465f5Selim Cinek maxDistance); 1904c6969a512cd70831249ec1d07691f16fe5465f5Selim Cinek animator.setDuration(properties.duration); 1914c6969a512cd70831249ec1d07691f16fe5465f5Selim Cinek animator.setInterpolator(properties.interpolator); 1924c6969a512cd70831249ec1d07691f16fe5465f5Selim Cinek } 1934c6969a512cd70831249ec1d07691f16fe5465f5Selim Cinek 1944c6969a512cd70831249ec1d07691f16fe5465f5Selim Cinek private AnimatorProperties getDismissingProperties(float currValue, float endValue, 1954c6969a512cd70831249ec1d07691f16fe5465f5Selim Cinek float velocity, float maxDistance) { 1961d480695df31f1c328473f32d5007cea6a03b6e0Jorim Jaggi float maxLengthSeconds = (float) (mMaxLengthSeconds 1971d480695df31f1c328473f32d5007cea6a03b6e0Jorim Jaggi * Math.pow(Math.abs(endValue - currValue) / maxDistance, 0.5f)); 1981d480695df31f1c328473f32d5007cea6a03b6e0Jorim Jaggi float diff = Math.abs(endValue - currValue); 1991d480695df31f1c328473f32d5007cea6a03b6e0Jorim Jaggi float velAbs = Math.abs(velocity); 200efbd7e3bb8244efae2561f0d9d7cedb36b1730bdJorim Jaggi float y2 = calculateLinearOutFasterInY2(velAbs); 201efbd7e3bb8244efae2561f0d9d7cedb36b1730bdJorim Jaggi 2022580a976ec93a01ed00fae51364ad872bc591d95Jorim Jaggi float startGradient = y2 / LINEAR_OUT_FASTER_IN_X2; 2032580a976ec93a01ed00fae51364ad872bc591d95Jorim Jaggi Interpolator mLinearOutFasterIn = new PathInterpolator(0, 0, LINEAR_OUT_FASTER_IN_X2, y2); 204efbd7e3bb8244efae2561f0d9d7cedb36b1730bdJorim Jaggi float durationSeconds = startGradient * diff / velAbs; 2051d480695df31f1c328473f32d5007cea6a03b6e0Jorim Jaggi if (durationSeconds <= maxLengthSeconds) { 2064c6969a512cd70831249ec1d07691f16fe5465f5Selim Cinek mAnimatorProperties.interpolator = mLinearOutFasterIn; 2071d480695df31f1c328473f32d5007cea6a03b6e0Jorim Jaggi } else if (velAbs >= mMinVelocityPxPerSecond) { 2081d480695df31f1c328473f32d5007cea6a03b6e0Jorim Jaggi 2091d480695df31f1c328473f32d5007cea6a03b6e0Jorim Jaggi // Cross fade between linear-out-faster-in and linear interpolator with current 2101d480695df31f1c328473f32d5007cea6a03b6e0Jorim Jaggi // velocity. 2111d480695df31f1c328473f32d5007cea6a03b6e0Jorim Jaggi durationSeconds = maxLengthSeconds; 2121d480695df31f1c328473f32d5007cea6a03b6e0Jorim Jaggi VelocityInterpolator velocityInterpolator 2131d480695df31f1c328473f32d5007cea6a03b6e0Jorim Jaggi = new VelocityInterpolator(durationSeconds, velAbs, diff); 2141d480695df31f1c328473f32d5007cea6a03b6e0Jorim Jaggi InterpolatorInterpolator superInterpolator = new InterpolatorInterpolator( 2151d480695df31f1c328473f32d5007cea6a03b6e0Jorim Jaggi velocityInterpolator, mLinearOutFasterIn, mLinearOutSlowIn); 2164c6969a512cd70831249ec1d07691f16fe5465f5Selim Cinek mAnimatorProperties.interpolator = superInterpolator; 2171d480695df31f1c328473f32d5007cea6a03b6e0Jorim Jaggi } else { 2181d480695df31f1c328473f32d5007cea6a03b6e0Jorim Jaggi 2191d480695df31f1c328473f32d5007cea6a03b6e0Jorim Jaggi // Just use a normal interpolator which doesn't take the velocity into account. 2201d480695df31f1c328473f32d5007cea6a03b6e0Jorim Jaggi durationSeconds = maxLengthSeconds; 221c18010f6720f606003cde3cd376ddacaca30f6e5Selim Cinek mAnimatorProperties.interpolator = Interpolators.FAST_OUT_LINEAR_IN; 2221d480695df31f1c328473f32d5007cea6a03b6e0Jorim Jaggi } 2234c6969a512cd70831249ec1d07691f16fe5465f5Selim Cinek mAnimatorProperties.duration = (long) (durationSeconds * 1000); 2244c6969a512cd70831249ec1d07691f16fe5465f5Selim Cinek return mAnimatorProperties; 2251d480695df31f1c328473f32d5007cea6a03b6e0Jorim Jaggi } 2261d480695df31f1c328473f32d5007cea6a03b6e0Jorim Jaggi 2271d480695df31f1c328473f32d5007cea6a03b6e0Jorim Jaggi /** 228efbd7e3bb8244efae2561f0d9d7cedb36b1730bdJorim Jaggi * Calculates the y2 control point for a linear-out-faster-in path interpolator depending on the 229efbd7e3bb8244efae2561f0d9d7cedb36b1730bdJorim Jaggi * velocity. The faster the velocity, the more "linear" the interpolator gets. 230efbd7e3bb8244efae2561f0d9d7cedb36b1730bdJorim Jaggi * 231efbd7e3bb8244efae2561f0d9d7cedb36b1730bdJorim Jaggi * @param velocity the velocity of the gesture. 232efbd7e3bb8244efae2561f0d9d7cedb36b1730bdJorim Jaggi * @return the y2 control point for a cubic bezier path interpolator 233efbd7e3bb8244efae2561f0d9d7cedb36b1730bdJorim Jaggi */ 234efbd7e3bb8244efae2561f0d9d7cedb36b1730bdJorim Jaggi private float calculateLinearOutFasterInY2(float velocity) { 235efbd7e3bb8244efae2561f0d9d7cedb36b1730bdJorim Jaggi float t = (velocity - mMinVelocityPxPerSecond) 236efbd7e3bb8244efae2561f0d9d7cedb36b1730bdJorim Jaggi / (mHighVelocityPxPerSecond - mMinVelocityPxPerSecond); 237efbd7e3bb8244efae2561f0d9d7cedb36b1730bdJorim Jaggi t = Math.max(0, Math.min(1, t)); 238efbd7e3bb8244efae2561f0d9d7cedb36b1730bdJorim Jaggi return (1 - t) * LINEAR_OUT_FASTER_IN_Y2_MIN + t * LINEAR_OUT_FASTER_IN_Y2_MAX; 239efbd7e3bb8244efae2561f0d9d7cedb36b1730bdJorim Jaggi } 240efbd7e3bb8244efae2561f0d9d7cedb36b1730bdJorim Jaggi 241efbd7e3bb8244efae2561f0d9d7cedb36b1730bdJorim Jaggi /** 2421d480695df31f1c328473f32d5007cea6a03b6e0Jorim Jaggi * @return the minimum velocity a gesture needs to have to be considered a fling 2431d480695df31f1c328473f32d5007cea6a03b6e0Jorim Jaggi */ 2441d480695df31f1c328473f32d5007cea6a03b6e0Jorim Jaggi public float getMinVelocityPxPerSecond() { 2451d480695df31f1c328473f32d5007cea6a03b6e0Jorim Jaggi return mMinVelocityPxPerSecond; 2461d480695df31f1c328473f32d5007cea6a03b6e0Jorim Jaggi } 2471d480695df31f1c328473f32d5007cea6a03b6e0Jorim Jaggi 2481d480695df31f1c328473f32d5007cea6a03b6e0Jorim Jaggi /** 24987cd5e71ec087e191b8baaa8913a878f92d4e10dJorim Jaggi * An interpolator which interpolates two interpolators with an interpolator. 25087cd5e71ec087e191b8baaa8913a878f92d4e10dJorim Jaggi */ 25187cd5e71ec087e191b8baaa8913a878f92d4e10dJorim Jaggi private static final class InterpolatorInterpolator implements Interpolator { 25287cd5e71ec087e191b8baaa8913a878f92d4e10dJorim Jaggi 25387cd5e71ec087e191b8baaa8913a878f92d4e10dJorim Jaggi private Interpolator mInterpolator1; 25487cd5e71ec087e191b8baaa8913a878f92d4e10dJorim Jaggi private Interpolator mInterpolator2; 25587cd5e71ec087e191b8baaa8913a878f92d4e10dJorim Jaggi private Interpolator mCrossfader; 25687cd5e71ec087e191b8baaa8913a878f92d4e10dJorim Jaggi 25787cd5e71ec087e191b8baaa8913a878f92d4e10dJorim Jaggi InterpolatorInterpolator(Interpolator interpolator1, Interpolator interpolator2, 25887cd5e71ec087e191b8baaa8913a878f92d4e10dJorim Jaggi Interpolator crossfader) { 25987cd5e71ec087e191b8baaa8913a878f92d4e10dJorim Jaggi mInterpolator1 = interpolator1; 26087cd5e71ec087e191b8baaa8913a878f92d4e10dJorim Jaggi mInterpolator2 = interpolator2; 26187cd5e71ec087e191b8baaa8913a878f92d4e10dJorim Jaggi mCrossfader = crossfader; 26287cd5e71ec087e191b8baaa8913a878f92d4e10dJorim Jaggi } 26387cd5e71ec087e191b8baaa8913a878f92d4e10dJorim Jaggi 26487cd5e71ec087e191b8baaa8913a878f92d4e10dJorim Jaggi @Override 26587cd5e71ec087e191b8baaa8913a878f92d4e10dJorim Jaggi public float getInterpolation(float input) { 26687cd5e71ec087e191b8baaa8913a878f92d4e10dJorim Jaggi float t = mCrossfader.getInterpolation(input); 26787cd5e71ec087e191b8baaa8913a878f92d4e10dJorim Jaggi return (1 - t) * mInterpolator1.getInterpolation(input) 26887cd5e71ec087e191b8baaa8913a878f92d4e10dJorim Jaggi + t * mInterpolator2.getInterpolation(input); 26987cd5e71ec087e191b8baaa8913a878f92d4e10dJorim Jaggi } 27087cd5e71ec087e191b8baaa8913a878f92d4e10dJorim Jaggi } 27187cd5e71ec087e191b8baaa8913a878f92d4e10dJorim Jaggi 27287cd5e71ec087e191b8baaa8913a878f92d4e10dJorim Jaggi /** 27387cd5e71ec087e191b8baaa8913a878f92d4e10dJorim Jaggi * An interpolator which interpolates with a fixed velocity. 27487cd5e71ec087e191b8baaa8913a878f92d4e10dJorim Jaggi */ 27587cd5e71ec087e191b8baaa8913a878f92d4e10dJorim Jaggi private static final class VelocityInterpolator implements Interpolator { 27687cd5e71ec087e191b8baaa8913a878f92d4e10dJorim Jaggi 27787cd5e71ec087e191b8baaa8913a878f92d4e10dJorim Jaggi private float mDurationSeconds; 27887cd5e71ec087e191b8baaa8913a878f92d4e10dJorim Jaggi private float mVelocity; 27987cd5e71ec087e191b8baaa8913a878f92d4e10dJorim Jaggi private float mDiff; 28087cd5e71ec087e191b8baaa8913a878f92d4e10dJorim Jaggi 28187cd5e71ec087e191b8baaa8913a878f92d4e10dJorim Jaggi private VelocityInterpolator(float durationSeconds, float velocity, float diff) { 28287cd5e71ec087e191b8baaa8913a878f92d4e10dJorim Jaggi mDurationSeconds = durationSeconds; 28387cd5e71ec087e191b8baaa8913a878f92d4e10dJorim Jaggi mVelocity = velocity; 28487cd5e71ec087e191b8baaa8913a878f92d4e10dJorim Jaggi mDiff = diff; 28587cd5e71ec087e191b8baaa8913a878f92d4e10dJorim Jaggi } 28687cd5e71ec087e191b8baaa8913a878f92d4e10dJorim Jaggi 28787cd5e71ec087e191b8baaa8913a878f92d4e10dJorim Jaggi @Override 28887cd5e71ec087e191b8baaa8913a878f92d4e10dJorim Jaggi public float getInterpolation(float input) { 28987cd5e71ec087e191b8baaa8913a878f92d4e10dJorim Jaggi float time = input * mDurationSeconds; 29087cd5e71ec087e191b8baaa8913a878f92d4e10dJorim Jaggi return time * mVelocity / mDiff; 29187cd5e71ec087e191b8baaa8913a878f92d4e10dJorim Jaggi } 29287cd5e71ec087e191b8baaa8913a878f92d4e10dJorim Jaggi } 2934c6969a512cd70831249ec1d07691f16fe5465f5Selim Cinek 2944c6969a512cd70831249ec1d07691f16fe5465f5Selim Cinek private static class AnimatorProperties { 2954c6969a512cd70831249ec1d07691f16fe5465f5Selim Cinek Interpolator interpolator; 2964c6969a512cd70831249ec1d07691f16fe5465f5Selim Cinek long duration; 2974c6969a512cd70831249ec1d07691f16fe5465f5Selim Cinek } 2984c6969a512cd70831249ec1d07691f16fe5465f5Selim Cinek 29987cd5e71ec087e191b8baaa8913a878f92d4e10dJorim Jaggi} 300