├── .gitignore ├── README-CN.md ├── README.md ├── build.gradle ├── example ├── .gitignore ├── build.gradle ├── proguard-rules.pro └── src │ ├── androidTest │ └── java │ │ └── com │ │ └── github │ │ └── hujiaweibujidao │ │ └── example │ │ ├── ApplicationTest.java │ │ └── MainActivityTest.java │ ├── main │ ├── AndroidManifest.xml │ ├── ic_launcher-web.png │ ├── java │ │ └── com │ │ │ └── github │ │ │ └── hujiaweibujidao │ │ │ └── example │ │ │ ├── activity │ │ │ ├── Bounce2Activity.java │ │ │ ├── BounceActivity.java │ │ │ ├── CustomActivity.java │ │ │ ├── Demo2Activity.java │ │ │ ├── DemoActivity.java │ │ │ ├── EvaluatorActivity.java │ │ │ ├── InterpolatorActivity.java │ │ │ └── MainActivity.java │ │ │ ├── adapter │ │ │ ├── EvaluatorAdapter.java │ │ │ └── InterpolatorAdapter.java │ │ │ └── view │ │ │ ├── CursorView.java │ │ │ ├── EvaluatorView.java │ │ │ └── InterpolatorView.java │ └── res │ │ ├── drawable │ │ └── circle.xml │ │ ├── layout │ │ ├── activity_demo.xml │ │ ├── activity_evaluator.xml │ │ ├── activity_interpolator.xml │ │ ├── activity_main.xml │ │ ├── adapter.xml │ │ └── item.xml │ │ ├── mipmap-hdpi │ │ └── ic_launcher.png │ │ ├── mipmap-mdpi │ │ └── ic_launcher.png │ │ ├── mipmap-xhdpi │ │ └── ic_launcher.png │ │ ├── mipmap-xxhdpi │ │ └── ic_launcher.png │ │ ├── mipmap-xxxhdpi │ │ └── ic_launcher.png │ │ ├── values-w820dp │ │ └── dimens.xml │ │ └── values │ │ ├── colors.xml │ │ ├── dimens.xml │ │ ├── strings.xml │ │ └── styles.xml │ └── test │ └── java │ └── com │ └── github │ └── hujiaweibujidao │ └── example │ └── ExampleUnitTest.java ├── gradle.properties ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat ├── library ├── .gitignore ├── build.gradle ├── proguard-rules.pro └── src │ ├── androidTest │ └── java │ │ └── com │ │ └── github │ │ └── hujiaweibujidao │ │ └── yava │ │ └── ApplicationTest.java │ ├── main │ ├── AndroidManifest.xml │ ├── java │ │ └── com │ │ │ └── github │ │ │ └── hujiaweibujidao │ │ │ └── yava │ │ │ ├── AbstractFunction.java │ │ │ ├── EasingFunction.java │ │ │ ├── Functions.java │ │ │ └── IFunction.java │ └── res │ │ └── values │ │ └── strings.xml │ └── test │ └── java │ └── com │ └── github │ └── hujiaweibujidao │ └── yava │ └── ExampleUnitTest.java ├── settings.gradle └── yava.gif /.gitignore: -------------------------------------------------------------------------------- 1 | *.iml 2 | .gradle 3 | /local.properties 4 | /.idea/workspace.xml 5 | /.idea/libraries 6 | .DS_Store 7 | /build 8 | /captures 9 | -------------------------------------------------------------------------------- /README-CN.md: -------------------------------------------------------------------------------- 1 | [![jitpack](https://www.jitpack.io/v/hujiaweibujidao/yava.svg)](https://www.jitpack.io/#hujiaweibujidao/yava) [![Android Arsenal](https://img.shields.io/badge/Android%20Arsenal-yava-brightgreen.svg?style=flat)](http://android-arsenal.com/details/1/3639) 2 | 3 | ## Yava 4 | 5 | > Yet Another View Animation ( a simple and elegant view animation helper library for Android) 6 | 7 | This library helps you convert any curve into ready-to-use `Interpolator` or `TypeEvaluator` for `ValueAnimator`, and thirty Rovert Penner's Easing Functions are already included. 8 | 9 | 关于本项目的创建缘由以及实现思路,欢迎阅读我写的这三篇文章,详细介绍了Android动画中的三个重要类:`ValueAnimator`、`TypeEvaluator`和`TimeInterpolator`,我保证您会有所收获的 😜 10 | 11 | [当数学遇上动画:讲述`ValueAnimator`、`TypeEvaluator`和`TimeInterpolator`之间的恩恩怨怨(1)](http://hujiaweibujidao.github.io/blog/2016/05/26/when-math-meets-android-animation/) 12 | [当数学遇上动画:讲述`ValueAnimator`、`TypeEvaluator`和`TimeInterpolator`之间的恩恩怨怨(2)](http://hujiaweibujidao.github.io/blog/2016/05/27/When-Math-meets-Android-Animation-2/) 13 | [当数学遇上动画:讲述`ValueAnimator`、`TypeEvaluator`和`TimeInterpolator`之间的恩恩怨怨(3)](http://hujiaweibujidao.github.io/blog/2016/05/27/When-Math-meets-Android-Animation-3/) 14 | 15 | 该项目实现的功能就是将抽象的函数曲线轻松转换成立即可用的`Interpolator`和`TypeEvaluator`,然后应用在Android动画中。这个项目还提供了常见的30个缓动函数(Easing Functions)的实现,它们既可以当做`Interpolator`来用,又可以当做`TypeEvaluator`来用,真的非常方便。 16 | 17 | ## Screenshot 18 | 19 | ![img](yava.gif) 20 | 21 | ## Usage 22 | 23 | 举个例子,以弹跳动画效果为例,可以直接使用`EasingFunction.BOUNCE_OUT`作为`Interpolator`或者`TypeEvaluator`来使用: 24 | 25 | 第一种方式:使用线性插值器和自定义的TypeEvaluator 26 | 27 | ```java 28 | ObjectAnimator animator1 = new ObjectAnimator(); 29 | animator1.setTarget(textView1); 30 | animator1.setPropertyName("translationY"); 31 | animator1.setFloatValues(0f, -100f); 32 | animator1.setDuration(1000); 33 | animator1.setInterpolator(new LinearInterpolator()); 34 | animator1.setEvaluator(EasingFunction.BOUNCE_OUT); //这里将EasingFunction.BOUNCE_OUT作为TypeEvaluator来使用 35 | animator1.start(); 36 | ``` 37 | 38 | 第二种方式:使用自定义的Interpolator和"线性估值器" 39 | 40 | ```java 41 | ObjectAnimator animator2 = new ObjectAnimator(); 42 | animator2.setTarget(textView2); 43 | animator2.setPropertyName("translationY"); 44 | animator2.setFloatValues(0f, -100f); 45 | animator2.setDuration(1000); 46 | animator2.setInterpolator(EasingFunction.BOUNCE_OUT); //这里将EasingFunction.BOUNCE_OUT作为Interpolator来使用 47 | animator2.setEvaluator(new FloatEvaluator()); 48 | animator2.start(); 49 | ``` 50 | 51 | 如果你想使用自己定义的函数来制作动画,可以使用`Functions`的`with`方法,传入一个实现了`IFunction`接口的类就行,返回值你既可以当做`Interpolator`,也可以当做`TypeEvaluator`来使用 52 | 53 | 代码示例: 54 | 55 | ```java 56 | ObjectAnimator animator1 = new ObjectAnimator(); 57 | animator1.setTarget(textView1); 58 | animator1.setPropertyName("translationY"); 59 | animator1.setFloatValues(0f, -100f); 60 | animator1.setDuration(1000); 61 | animator1.setInterpolator(new LinearInterpolator()); 62 | animator1.setEvaluator(Functions.with(new IFunction() { //自定义为TypeEvaluator 63 | @Override 64 | public float getValue(float input) { 65 | return input * 2 + 3; 66 | } 67 | })); 68 | animator1.start(); 69 | ``` 70 | 71 | 或者这样: 72 | 73 | 74 | ```java 75 | ObjectAnimator animator2 = new ObjectAnimator(); 76 | animator2.setTarget(textView2); 77 | animator2.setPropertyName("translationY"); 78 | animator2.setFloatValues(0f, -100f); 79 | animator2.setDuration(1000); 80 | animator2.setInterpolator(Functions.with(new IFunction() { //自定义为Interpolator 81 | @Override 82 | public float getValue(float input) { 83 | return input * 2 + 3; 84 | } 85 | })); 86 | animator2.setEvaluator(new FloatEvaluator()); 87 | animator2.start(); 88 | ``` 89 | 90 | ## Setup 91 | 92 | 你只需要拷贝`library`中的4个重要类到你的项目中就行了! 93 | 94 | 或者 95 | 96 | 1.在项目根目录的`build.gradle`文件中加入 97 | 98 | ``` 99 | allprojects { 100 | repositories { 101 | ... 102 | maven { url "https://www.jitpack.io" } 103 | } 104 | } 105 | ``` 106 | 107 | 2.然后在需要的`build.gradle`文件中加入依赖 108 | 109 | ``` 110 | dependencies { 111 | compile 'com.github.hujiaweibujidao:yava:1.0.0' 112 | } 113 | ``` 114 | 115 | ## Documentation 116 | 117 | 项目只有4个核心类,放在`library`中 118 | 119 | (1) `IFunction`接口 120 | 121 | ```java 122 | /** 123 | * 函数接口:给定输入,得到输出 124 | */ 125 | public interface IFunction { 126 | float getValue(float input); 127 | } 128 | ``` 129 | 130 | (2)`AbstractFunction`抽象类 131 | 132 | ```java 133 | /** 134 | * 抽象函数实现,既可以当做简单函数使用,也可以当做Interpolator或者TypeEvaluator去用于制作动画 135 | */ 136 | public abstract class AbstractFunction implements IFunction, Interpolator, TypeEvaluator { 137 | 138 | @Override 139 | public float getInterpolation(float input) { 140 | return getValue(input); 141 | } 142 | 143 | @Override 144 | public Float evaluate(float fraction, Float startValue, Float endValue) { 145 | return startValue + getValue(fraction) * (endValue - startValue); 146 | } 147 | } 148 | ``` 149 | 150 | (3)`Functions`类 151 | 152 | ```java 153 | /** 154 | * 工具类,将自定义的函数快速封装成AbstractFunction 155 | */ 156 | class Functions { 157 | 158 | public static AbstractFunction with(final IFunction function) { 159 | return new AbstractFunction() { 160 | @Override 161 | public float getValue(float input) { 162 | return function.getValue(input); 163 | } 164 | }; 165 | } 166 | } 167 | ``` 168 | 169 | (4)`EasingFunction`枚举:包含了30个常见的缓动函数 170 | 171 | ```java 172 | /** 173 | * 常见的30个缓动函数的实现 174 | */ 175 | public enum EasingFunction implements IFunction, Interpolator, TypeEvaluator { 176 | 177 | /* ------------------------------------------------------------------------------------------- */ 178 | /* BACK 179 | /* ------------------------------------------------------------------------------------------- */ 180 | BACK_IN { 181 | @Override 182 | public float getValue(float input) { 183 | return input * input * ((1.70158f + 1) * input - 1.70158f); 184 | } 185 | }, 186 | BACK_OUT { 187 | @Override 188 | public float getValue(float input) { 189 | return ((input = input - 1) * input * ((1.70158f + 1) * input + 1.70158f) + 1); 190 | } 191 | }, 192 | BACK_INOUT { 193 | @Override 194 | public float getValue(float input) { 195 | float s = 1.70158f; 196 | if ((input *= 2) < 1) { 197 | return 0.5f * (input * input * (((s *= (1.525f)) + 1) * input - s)); 198 | } 199 | return 0.5f * ((input -= 2) * input * (((s *= (1.525f)) + 1) * input + s) + 2); 200 | } 201 | }, 202 | 203 | //other easing functions ...... 204 | 205 | //如果这个function在求值的时候需要duration作为参数的话,那么可以通过setDuration来设置,否则使用默认值 206 | private float duration = 1000f; 207 | 208 | public float getDuration() { 209 | return duration; 210 | } 211 | 212 | public EasingFunction setDuration(float duration) { 213 | this.duration = duration; 214 | return this; 215 | } 216 | 217 | //将Function当做Interpolator使用,默认的实现,不需要枚举元素去重新实现 218 | @Override 219 | public float getInterpolation(float input) { 220 | return getValue(input); 221 | } 222 | 223 | //将Function当做TypeEvaluator使用,默认的实现,不需要枚举元素去重新实现 224 | @Override 225 | public Float evaluate(float fraction, Float startValue, Float endValue) { 226 | return startValue + getValue(fraction) * (endValue - startValue); 227 | } 228 | 229 | //几个数学常量 230 | public static final float PI = (float) Math.PI; 231 | public static float TWO_PI = PI * 2.0f; 232 | public static float HALF_PI = PI * 0.5f; 233 | } 234 | ``` 235 | 236 | ## Reference 237 | 238 | 本项目主要参考了以下项目和内容 239 | 1.[EaseInterpolator](https://github.com/cimi-chen/EaseInterpolator) 240 | 2.[AnimationEasingFunctions](https://github.com/daimajia/AnimationEasingFunctions) 241 | 3.[easings.net](http://easings.net/) 242 | 243 | ## License 244 | 245 | ``` 246 | The MIT License (MIT) 247 | 248 | Copyright (c) 2016 Hujiawei 249 | 250 | Permission is hereby granted, free of charge, to any person obtaining a copy 251 | of this software and associated documentation files (the "Software"), to deal 252 | in the Software without restriction, including without limitation the rights 253 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 254 | copies of the Software, and to permit persons to whom the Software is 255 | furnished to do so, subject to the following conditions: 256 | 257 | The above copyright notice and this permission notice shall be included in all 258 | copies or substantial portions of the Software. 259 | 260 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 261 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 262 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 263 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 264 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 265 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 266 | SOFTWARE. 267 | ``` 268 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | [中文说明](README-CN.md) [![jitpack](https://www.jitpack.io/v/hujiaweibujidao/yava.svg)](https://www.jitpack.io/#hujiaweibujidao/yava) [![Android Arsenal](https://img.shields.io/badge/Android%20Arsenal-yava-brightgreen.svg?style=flat)](http://android-arsenal.com/details/1/3639) 2 | 3 | ## Yava 4 | 5 | > Yet Another View Animation ( a simple and elegant view animation helper library for Android) 6 | 7 | This library helps you convert any curve into ready-to-use `Interpolator` or `TypeEvaluator` for `ValueAnimator`, and thirty Rovert Penner's Easing Functions are already included. 8 | 9 | You may read the following three articles to know about the reason why I create this project, and how to implement it. They fully described the relations among `ValueAnimator`、`TypeEvaluator` and `TimeInterpolator`, hope it helps. 10 | 11 | [When Math Meets Animation(1)](https://javayhu.github.io/blog/2016-05-26-when-math-meets-android-animation-1) 12 | [When Math Meets Animation(2)](https://javayhu.github.io/blog/2016-05-27-When-Math-meets-Android-Animation-2) 13 | [When Math Meets Animation(3)](https://javayhu.github.io/blog/2016-05-28-When-Math-meets-Android-Animation-3) 14 | 15 | ## Screenshot 16 | 17 | ![img](yava.gif) 18 | 19 | ## Usage 20 | 21 | For example, if you want to create a `BOUNCE_OUT` animation, you can directly use `EasingFunction.BOUNCE_OUT` as `Interpolator` or `TypeEvaluator` for your `ValueAnimator`. 22 | 23 | Option 1: use `LinearInterpolator` with `EasingFunction.BOUNCE_OUT` (as `TypeEvaluator`) 24 | 25 | ```java 26 | ObjectAnimator animator1 = new ObjectAnimator(); 27 | animator1.setTarget(textView1); 28 | animator1.setPropertyName("translationY"); 29 | animator1.setFloatValues(0f, -100f); 30 | animator1.setDuration(1000); 31 | 32 | animator1.setInterpolator(new LinearInterpolator()); 33 | animator1.setEvaluator(EasingFunction.BOUNCE_OUT); //use `EasingFunction.BOUNCE_OUT` as `TypeEvaluator` 34 | 35 | animator1.start(); 36 | ``` 37 | 38 | Option 2: use `EasingFunction.BOUNCE_OUT` (as `Interpolator`) with `FloatEvaluator` (`"Linear TypeEvaluator"`) 39 | 40 | ```java 41 | ObjectAnimator animator2 = new ObjectAnimator(); 42 | animator2.setTarget(textView2); 43 | animator2.setPropertyName("translationY"); 44 | animator2.setFloatValues(0f, -100f); 45 | animator2.setDuration(1000); 46 | 47 | animator2.setInterpolator(EasingFunction.BOUNCE_OUT); //use `EasingFunction.BOUNCE_OUT` as `Interpolator` 48 | animator2.setEvaluator(new FloatEvaluator()); 49 | 50 | animator2.start(); 51 | ``` 52 | 53 | Want to use your customized function curve? It's simple! 54 | Try `Functions.with(IFunction youFunctionImplementation)`! 55 | 56 | Example 1: use it as `TypeEvaluator` 57 | 58 | ```java 59 | ObjectAnimator animator1 = new ObjectAnimator(); 60 | animator1.setTarget(textView1); 61 | animator1.setPropertyName("translationY"); 62 | animator1.setFloatValues(0f, -100f); 63 | animator1.setDuration(1000); 64 | 65 | animator1.setInterpolator(new LinearInterpolator()); 66 | animator1.setEvaluator(Functions.with(new IFunction() { //customized TypeEvaluator 67 | @Override 68 | public float getValue(float input) { 69 | return input * 2 + 3; 70 | } 71 | })); 72 | 73 | animator1.start(); 74 | ``` 75 | 76 | Or you can also use it as `Interpolator`: 77 | 78 | ```java 79 | ObjectAnimator animator2 = new ObjectAnimator(); 80 | animator2.setTarget(textView2); 81 | animator2.setPropertyName("translationY"); 82 | animator2.setFloatValues(0f, -100f); 83 | animator2.setDuration(1000); 84 | 85 | animator2.setInterpolator(Functions.with(new IFunction() { //customized Interpolator 86 | @Override 87 | public float getValue(float input) { 88 | return input * 2 + 3; 89 | } 90 | })); 91 | animator2.setEvaluator(new FloatEvaluator()); 92 | 93 | animator2.start(); 94 | ``` 95 | 96 | ## Setup 97 | 98 | Copy those four classes into your project, then you are set! 99 | 100 | OR 101 | 102 | 1.add this in your `build.gradle` file in root project 103 | 104 | ``` 105 | allprojects { 106 | repositories { 107 | ... 108 | maven { url "https://www.jitpack.io" } 109 | } 110 | } 111 | ``` 112 | 113 | 2.add the following dependency 114 | 115 | ``` 116 | dependencies { 117 | compile 'com.github.hujiaweibujidao:yava:1.0.0' 118 | } 119 | ``` 120 | 121 | ## Documentation 122 | 123 | There are only four core classes in `library`. 124 | 125 | (1) `IFunction`: interface 126 | 127 | ```java 128 | /** 129 | * Function Interface: given input, get the value result 130 | */ 131 | public interface IFunction { 132 | float getValue(float input); 133 | } 134 | ``` 135 | 136 | (2)`AbstractFunction`: abstract class 137 | 138 | ```java 139 | /** 140 | * abstract function, you can use it as `Interpolator` or `TypeEvaluator` 141 | */ 142 | public abstract class AbstractFunction implements IFunction, Interpolator, TypeEvaluator { 143 | 144 | @Override 145 | public float getInterpolation(float input) { 146 | return getValue(input); 147 | } 148 | 149 | @Override 150 | public Float evaluate(float fraction, Float startValue, Float endValue) { 151 | return startValue + getValue(fraction) * (endValue - startValue); 152 | } 153 | } 154 | ``` 155 | 156 | (3)`Functions`: class 157 | 158 | ```java 159 | /** 160 | * convert any function curve to ready-to-use AbstractFunction 161 | */ 162 | class Functions { 163 | 164 | public static AbstractFunction with(final IFunction function) { 165 | return new AbstractFunction() { 166 | @Override 167 | public float getValue(float input) { 168 | return function.getValue(input); 169 | } 170 | }; 171 | } 172 | } 173 | ``` 174 | 175 | (4)`EasingFunction`: enum with thirty Rovert Penner's Easing Functions included 176 | 177 | ```java 178 | /** 179 | * thirty Rovert Penner's Easing Functions 180 | */ 181 | public enum EasingFunction implements IFunction, Interpolator, TypeEvaluator { 182 | 183 | /* ------------------------------------------------------------------------------------------- */ 184 | /* BACK 185 | /* ------------------------------------------------------------------------------------------- */ 186 | BACK_IN { 187 | @Override 188 | public float getValue(float input) { 189 | return input * input * ((1.70158f + 1) * input - 1.70158f); 190 | } 191 | }, 192 | BACK_OUT { 193 | @Override 194 | public float getValue(float input) { 195 | return ((input = input - 1) * input * ((1.70158f + 1) * input + 1.70158f) + 1); 196 | } 197 | }, 198 | BACK_INOUT { 199 | @Override 200 | public float getValue(float input) { 201 | float s = 1.70158f; 202 | if ((input *= 2) < 1) { 203 | return 0.5f * (input * input * (((s *= (1.525f)) + 1) * input - s)); 204 | } 205 | return 0.5f * ((input -= 2) * input * (((s *= (1.525f)) + 1) * input + s) + 2); 206 | } 207 | }, 208 | 209 | //other easing functions ...... 210 | 211 | private float duration = 1000f; 212 | 213 | public float getDuration() { 214 | return duration; 215 | } 216 | 217 | public EasingFunction setDuration(float duration) { 218 | this.duration = duration; 219 | return this; 220 | } 221 | 222 | @Override 223 | public float getInterpolation(float input) { 224 | return getValue(input); 225 | } 226 | 227 | @Override 228 | public Float evaluate(float fraction, Float startValue, Float endValue) { 229 | return startValue + getValue(fraction) * (endValue - startValue); 230 | } 231 | 232 | //Math constants 233 | public static final float PI = (float) Math.PI; 234 | public static float TWO_PI = PI * 2.0f; 235 | public static float HALF_PI = PI * 0.5f; 236 | } 237 | ``` 238 | 239 | ## References 240 | 241 | 1.[EaseInterpolator](https://github.com/cimi-chen/EaseInterpolator) 242 | 2.[AnimationEasingFunctions](https://github.com/daimajia/AnimationEasingFunctions) 243 | 3.[easings.net](http://easings.net/) 244 | 245 | ### [wava](https://github.com/hujiaweibujidao/wava) 246 | 247 | Currently I'm planning to build another fancy animation library named [`wava`](https://github.com/hujiaweibujidao/wava) for Android, follow that project or my Github if you have any interest in it. 😄 248 | 249 | ## License 250 | 251 | ``` 252 | The MIT License (MIT) 253 | 254 | Copyright (c) 2016 Hujiawei 255 | 256 | Permission is hereby granted, free of charge, to any person obtaining a copy 257 | of this software and associated documentation files (the "Software"), to deal 258 | in the Software without restriction, including without limitation the rights 259 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 260 | copies of the Software, and to permit persons to whom the Software is 261 | furnished to do so, subject to the following conditions: 262 | 263 | The above copyright notice and this permission notice shall be included in all 264 | copies or substantial portions of the Software. 265 | 266 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 267 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 268 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 269 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 270 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 271 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 272 | SOFTWARE. 273 | ``` 274 | -------------------------------------------------------------------------------- /build.gradle: -------------------------------------------------------------------------------- 1 | // Top-level build file where you can add configuration options common to all sub-projects/modules. 2 | 3 | buildscript { 4 | repositories { 5 | jcenter() 6 | } 7 | dependencies { 8 | classpath 'com.android.tools.build:gradle:2.1.0' 9 | 10 | classpath 'com.github.dcendents:android-maven-gradle-plugin:1.3' 11 | // NOTE: Do not place your application dependencies here; they belong 12 | // in the individual module build.gradle files 13 | } 14 | } 15 | 16 | allprojects { 17 | repositories { 18 | jcenter() 19 | } 20 | } 21 | 22 | task clean(type: Delete) { 23 | delete rootProject.buildDir 24 | } 25 | -------------------------------------------------------------------------------- /example/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /example/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.application' 2 | 3 | android { 4 | compileSdkVersion 23 5 | buildToolsVersion "23.0.3" 6 | 7 | defaultConfig { 8 | applicationId "com.github.hujiaweibujidao.yava" 9 | minSdkVersion 16 10 | targetSdkVersion 23 11 | versionCode 1 12 | versionName "1.0" 13 | } 14 | buildTypes { 15 | release { 16 | minifyEnabled false 17 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' 18 | } 19 | } 20 | } 21 | 22 | dependencies { 23 | compile fileTree(dir: 'libs', include: ['*.jar']) 24 | testCompile 'junit:junit:4.12' 25 | compile 'com.android.support:appcompat-v7:23.4.0' 26 | compile project(':library') 27 | } 28 | -------------------------------------------------------------------------------- /example/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # By default, the flags in this file are appended to flags specified 3 | # in /Users/hujiawei/Android/android_sdk/tools/proguard/proguard-android.txt 4 | # You can edit the include path and order by changing the proguardFiles 5 | # directive in build.gradle. 6 | # 7 | # For more details, see 8 | # http://developer.android.com/guide/developing/tools/proguard.html 9 | 10 | # Add any project specific keep options here: 11 | 12 | # If your project uses WebView with JS, uncomment the following 13 | # and specify the fully qualified class name to the JavaScript interface 14 | # class: 15 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 16 | # public *; 17 | #} 18 | -------------------------------------------------------------------------------- /example/src/androidTest/java/com/github/hujiaweibujidao/example/ApplicationTest.java: -------------------------------------------------------------------------------- 1 | package com.github.hujiaweibujidao.example; 2 | 3 | import android.app.Application; 4 | import android.test.ApplicationTestCase; 5 | 6 | /** 7 | * Testing Fundamentals 8 | */ 9 | public class ApplicationTest extends ApplicationTestCase { 10 | public ApplicationTest() { 11 | super(Application.class); 12 | } 13 | } -------------------------------------------------------------------------------- /example/src/androidTest/java/com/github/hujiaweibujidao/example/MainActivityTest.java: -------------------------------------------------------------------------------- 1 | package com.github.hujiaweibujidao.example; 2 | 3 | import android.test.AndroidTestCase; 4 | import android.util.Log; 5 | import android.widget.Toast; 6 | 7 | /** 8 | * @author hujiawei 16/5/25 9 | */ 10 | public class MainActivityTest extends AndroidTestCase { 11 | 12 | public void setUp() throws Exception { 13 | 14 | } 15 | 16 | public void tearDown() throws Exception { 17 | 18 | } 19 | 20 | public void testOnCreate() throws Exception { 21 | Log.d("test","ok"); 22 | Toast.makeText(getContext(), "test ok", Toast.LENGTH_SHORT).show(); 23 | } 24 | } -------------------------------------------------------------------------------- /example/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | -------------------------------------------------------------------------------- /example/src/main/ic_launcher-web.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/javayhu/yava/ca558f24c15b584eb463054620ea3efc85700e91/example/src/main/ic_launcher-web.png -------------------------------------------------------------------------------- /example/src/main/java/com/github/hujiaweibujidao/example/activity/Bounce2Activity.java: -------------------------------------------------------------------------------- 1 | package com.github.hujiaweibujidao.example.activity; 2 | 3 | import android.animation.FloatEvaluator; 4 | import android.animation.ObjectAnimator; 5 | import android.os.Bundle; 6 | import android.support.v7.app.AppCompatActivity; 7 | import android.view.View; 8 | import android.view.animation.LinearInterpolator; 9 | import android.widget.Button; 10 | import android.widget.TextView; 11 | 12 | import com.github.hujiaweibujidao.yava.EasingFunction; 13 | import com.github.hujiaweibujidao.example.R; 14 | 15 | /** 16 | * 演示LinearInterpolator和TypeEvaluator 与 TimeInterpolator和LinearEvaluator 的动画效果一样 17 | * 这里使用ObjectAnimator来验证,弹跳效果 18 | */ 19 | public class Bounce2Activity extends AppCompatActivity { 20 | 21 | TextView textView1; 22 | TextView textView2; 23 | Button buttonStart; 24 | Button buttonStart2; 25 | Button buttonStartAll; 26 | 27 | @Override 28 | protected void onCreate(Bundle savedInstanceState) { 29 | super.onCreate(savedInstanceState); 30 | setContentView(R.layout.activity_demo); 31 | 32 | textView1 = (TextView) findViewById(R.id.textview1); 33 | textView2 = (TextView) findViewById(R.id.textview2); 34 | buttonStart = (Button) findViewById(R.id.buttonStart1); 35 | buttonStart2 = (Button) findViewById(R.id.buttonStart2); 36 | buttonStartAll = (Button) findViewById(R.id.buttonStartAll); 37 | 38 | buttonStart.setOnClickListener(new View.OnClickListener() { 39 | @Override 40 | public void onClick(View v) { 41 | startAnimator1(); 42 | } 43 | }); 44 | buttonStart2.setOnClickListener(new View.OnClickListener() { 45 | @Override 46 | public void onClick(View v) { 47 | startAnimator2(); 48 | } 49 | }); 50 | buttonStartAll.setOnClickListener(new View.OnClickListener() { 51 | @Override 52 | public void onClick(View v) { 53 | startAnimator1(); 54 | startAnimator2(); 55 | } 56 | }); 57 | } 58 | 59 | private void startAnimator2() { 60 | ObjectAnimator animator2 = new ObjectAnimator(); 61 | animator2.setTarget(textView2); 62 | animator2.setPropertyName("translationY"); 63 | animator2.setFloatValues(0f, -100f); 64 | animator2.setDuration(1000); 65 | animator2.setInterpolator(EasingFunction.BOUNCE_OUT); 66 | animator2.setEvaluator(new FloatEvaluator()); 67 | animator2.start(); 68 | } 69 | 70 | private void startAnimator1() { 71 | ObjectAnimator animator1 = new ObjectAnimator(); 72 | animator1.setTarget(textView1); 73 | animator1.setPropertyName("translationY"); 74 | animator1.setFloatValues(0f, -100f); 75 | animator1.setDuration(1000); 76 | animator1.setInterpolator(new LinearInterpolator()); 77 | animator1.setEvaluator(EasingFunction.BOUNCE_OUT); 78 | animator1.start(); 79 | } 80 | } 81 | 82 | -------------------------------------------------------------------------------- /example/src/main/java/com/github/hujiaweibujidao/example/activity/BounceActivity.java: -------------------------------------------------------------------------------- 1 | package com.github.hujiaweibujidao.example.activity; 2 | 3 | import android.animation.FloatEvaluator; 4 | import android.animation.ObjectAnimator; 5 | import android.animation.TimeInterpolator; 6 | import android.animation.TypeEvaluator; 7 | import android.os.Bundle; 8 | import android.support.v7.app.AppCompatActivity; 9 | import android.view.View; 10 | import android.view.animation.LinearInterpolator; 11 | import android.widget.Button; 12 | import android.widget.TextView; 13 | 14 | import com.github.hujiaweibujidao.example.R; 15 | 16 | /** 17 | * 演示LinearInterpolator和TypeEvaluator 与 TimeInterpolator和LinearEvaluator 的动画效果一样 18 | * 这里使用ObjectAnimator来验证,弹跳效果 19 | */ 20 | public class BounceActivity extends AppCompatActivity { 21 | 22 | TextView textView1; 23 | TextView textView2; 24 | Button buttonStart; 25 | Button buttonStart2; 26 | Button buttonStartAll; 27 | 28 | @Override 29 | protected void onCreate(Bundle savedInstanceState) { 30 | super.onCreate(savedInstanceState); 31 | setContentView(R.layout.activity_demo); 32 | 33 | textView1 = (TextView) findViewById(R.id.textview1); 34 | textView2 = (TextView) findViewById(R.id.textview2); 35 | buttonStart = (Button) findViewById(R.id.buttonStart1); 36 | buttonStart2 = (Button) findViewById(R.id.buttonStart2); 37 | buttonStartAll = (Button) findViewById(R.id.buttonStartAll); 38 | 39 | buttonStart.setOnClickListener(new View.OnClickListener() { 40 | @Override 41 | public void onClick(View v) { 42 | startAnimator1(); 43 | } 44 | }); 45 | buttonStart2.setOnClickListener(new View.OnClickListener() { 46 | @Override 47 | public void onClick(View v) { 48 | startAnimator2(); 49 | } 50 | }); 51 | buttonStartAll.setOnClickListener(new View.OnClickListener() { 52 | @Override 53 | public void onClick(View v) { 54 | startAnimator1(); 55 | startAnimator2(); 56 | } 57 | }); 58 | } 59 | 60 | private void startAnimator2() { 61 | final ObjectAnimator animator2 = new ObjectAnimator(); 62 | animator2.setTarget(textView2); 63 | animator2.setPropertyName("translationY"); 64 | animator2.setFloatValues(0f, -100f); 65 | animator2.setDuration(1000); 66 | animator2.setInterpolator(new TimeInterpolator() { 67 | @Override 68 | public float getInterpolation(float input) { 69 | if (input < (1 / 2.75)) 70 | return (7.5625f * input * input); 71 | else if (input < (2 / 2.75)) 72 | return (7.5625f * (input -= (1.5f / 2.75f)) * input + 0.75f); 73 | else if (input < (2.5 / 2.75)) 74 | return (7.5625f * (input -= (2.25f / 2.75f)) * input + 0.9375f); 75 | else 76 | return (7.5625f * (input -= (2.625f / 2.75f)) * input + 0.984375f); 77 | } 78 | }); 79 | animator2.setEvaluator(new FloatEvaluator()); 80 | animator2.start(); 81 | } 82 | 83 | private void startAnimator1() { 84 | final ObjectAnimator animator1 = new ObjectAnimator(); 85 | animator1.setTarget(textView1); 86 | animator1.setPropertyName("translationY"); 87 | animator1.setFloatValues(0f, -100f); 88 | animator1.setDuration(1000); 89 | animator1.setInterpolator(new LinearInterpolator()); 90 | animator1.setEvaluator(new TypeEvaluator() { 91 | @Override 92 | public Number evaluate(float fraction, Number startValue, Number endValue) { 93 | float t = animator1.getDuration() * fraction;//已经过去的时间 94 | float b = startValue.floatValue();//起始值 95 | float c = endValue.floatValue() - startValue.floatValue();//结束值与起始值之间的差值 96 | float d = animator1.getDuration();//总的时间间隔,t/d 就是已经过去的时间占总时间间隔的比率 97 | 98 | if ((t /= d) < (1 / 2.75f)) { 99 | return c * (7.5625f * t * t) + b; 100 | } else if (t < (2 / 2.75f)) { 101 | return c * (7.5625f * (t -= (1.5f / 2.75f)) * t + .75f) + b; 102 | } else if (t < (2.5 / 2.75)) { 103 | return c * (7.5625f * (t -= (2.25f / 2.75f)) * t + .9375f) + b; 104 | } else { 105 | return c * (7.5625f * (t -= (2.625f / 2.75f)) * t + .984375f) + b; 106 | } 107 | } 108 | }); 109 | animator1.start(); 110 | } 111 | } 112 | 113 | -------------------------------------------------------------------------------- /example/src/main/java/com/github/hujiaweibujidao/example/activity/CustomActivity.java: -------------------------------------------------------------------------------- 1 | package com.github.hujiaweibujidao.example.activity; 2 | 3 | import android.animation.FloatEvaluator; 4 | import android.animation.ObjectAnimator; 5 | import android.os.Bundle; 6 | import android.support.v7.app.AppCompatActivity; 7 | import android.view.View; 8 | import android.view.animation.LinearInterpolator; 9 | import android.widget.Button; 10 | import android.widget.TextView; 11 | 12 | import com.github.hujiaweibujidao.yava.Functions; 13 | import com.github.hujiaweibujidao.yava.IFunction; 14 | import com.github.hujiaweibujidao.example.R; 15 | 16 | /** 17 | * 演示如何自定义function拿到Interpolator或者TypeEvaluator 18 | */ 19 | public class CustomActivity extends AppCompatActivity { 20 | 21 | TextView textView1; 22 | TextView textView2; 23 | Button buttonStart; 24 | Button buttonStart2; 25 | Button buttonStartAll; 26 | 27 | @Override 28 | protected void onCreate(Bundle savedInstanceState) { 29 | super.onCreate(savedInstanceState); 30 | setContentView(R.layout.activity_demo); 31 | 32 | textView1 = (TextView) findViewById(R.id.textview1); 33 | textView2 = (TextView) findViewById(R.id.textview2); 34 | buttonStart = (Button) findViewById(R.id.buttonStart1); 35 | buttonStart2 = (Button) findViewById(R.id.buttonStart2); 36 | buttonStartAll = (Button) findViewById(R.id.buttonStartAll); 37 | 38 | buttonStart.setOnClickListener(new View.OnClickListener() { 39 | @Override 40 | public void onClick(View v) { 41 | startAnimator1(); 42 | } 43 | }); 44 | buttonStart2.setOnClickListener(new View.OnClickListener() { 45 | @Override 46 | public void onClick(View v) { 47 | startAnimator2(); 48 | } 49 | }); 50 | buttonStartAll.setOnClickListener(new View.OnClickListener() { 51 | @Override 52 | public void onClick(View v) { 53 | startAnimator1(); 54 | startAnimator2(); 55 | } 56 | }); 57 | } 58 | 59 | private void startAnimator2() { 60 | ObjectAnimator animator2 = new ObjectAnimator(); 61 | animator2.setTarget(textView2); 62 | animator2.setPropertyName("translationY"); 63 | animator2.setFloatValues(0f, -100f); 64 | animator2.setDuration(1000); 65 | animator2.setInterpolator(Functions.with(new IFunction() { 66 | @Override 67 | public float getValue(float input) { 68 | return input * 2 + 3; 69 | } 70 | })); 71 | animator2.setEvaluator(new FloatEvaluator()); 72 | animator2.start(); 73 | } 74 | 75 | private void startAnimator1() { 76 | ObjectAnimator animator1 = new ObjectAnimator(); 77 | animator1.setTarget(textView1); 78 | animator1.setPropertyName("translationY"); 79 | animator1.setFloatValues(0f, -100f); 80 | animator1.setDuration(1000); 81 | animator1.setInterpolator(new LinearInterpolator()); 82 | animator1.setEvaluator(Functions.with(new IFunction() { 83 | @Override 84 | public float getValue(float input) { 85 | return input * 2 + 3; 86 | } 87 | })); 88 | animator1.start(); 89 | } 90 | } 91 | 92 | -------------------------------------------------------------------------------- /example/src/main/java/com/github/hujiaweibujidao/example/activity/Demo2Activity.java: -------------------------------------------------------------------------------- 1 | package com.github.hujiaweibujidao.example.activity; 2 | 3 | import android.animation.TypeEvaluator; 4 | import android.animation.ValueAnimator; 5 | import android.os.Bundle; 6 | import android.support.v7.app.AppCompatActivity; 7 | import android.util.Log; 8 | import android.view.View; 9 | import android.view.animation.Interpolator; 10 | import android.view.animation.LinearInterpolator; 11 | import android.widget.Button; 12 | 13 | import com.github.hujiaweibujidao.example.R; 14 | 15 | /** 16 | * 演示LinearInterpolator和TypeEvaluator 与 TimeInterpolator和LinearEvaluator 的动画效果一样 17 | * 这里使用ValueAnimator来验证 18 | */ 19 | public class Demo2Activity extends AppCompatActivity { 20 | 21 | Button buttonStart; 22 | 23 | @Override 24 | protected void onCreate(Bundle savedInstanceState) { 25 | super.onCreate(savedInstanceState); 26 | setContentView(R.layout.activity_demo); 27 | 28 | findViewById(R.id.textview1).setVisibility(View.GONE); 29 | findViewById(R.id.textview2).setVisibility(View.GONE); 30 | findViewById(R.id.buttonStart1).setVisibility(View.GONE); 31 | findViewById(R.id.buttonStart2).setVisibility(View.GONE); 32 | 33 | buttonStart = (Button) findViewById(R.id.buttonStartAll); 34 | buttonStart.setText("Click and see your log"); 35 | 36 | buttonStart.setOnClickListener(new View.OnClickListener() { 37 | @Override 38 | public void onClick(View v) { 39 | 40 | ValueAnimator animator1 = new ValueAnimator(); 41 | animator1.setFloatValues(0.0f, 1.0f); 42 | animator1.setDuration(1000); 43 | animator1.setInterpolator(new LinearInterpolator());//默认就是LinearInterpolator 44 | animator1.setEvaluator(new TypeEvaluator() { 45 | @Override 46 | public Object evaluate(float fraction, Object startValue, Object endValue) { 47 | return (float) startValue + ((float) endValue - (float) startValue) * (fraction*fraction); 48 | } 49 | }); 50 | animator1.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { 51 | @Override 52 | public void onAnimationUpdate(ValueAnimator animation) { 53 | Log.e("demo 1", "" + animation.getAnimatedValue()); 54 | } 55 | }); 56 | 57 | ValueAnimator animator2 = new ValueAnimator(); 58 | animator2.setFloatValues(0.0f, 1.0f); 59 | animator2.setDuration(1000); 60 | animator2.setInterpolator(new Interpolator() { 61 | @Override 62 | public float getInterpolation(float input) { 63 | return input * input; 64 | } 65 | }); 66 | animator2.setEvaluator(new TypeEvaluator() { 67 | @Override 68 | public Object evaluate(float fraction, Object startValue, Object endValue) { 69 | return (float) startValue + ((float) endValue - (float) startValue) * (fraction); 70 | } 71 | }); 72 | animator2.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { 73 | @Override 74 | public void onAnimationUpdate(ValueAnimator animation) { 75 | Log.e("demo 2", "" + animation.getAnimatedValue()); 76 | } 77 | }); 78 | 79 | animator1.start(); 80 | animator2.start(); 81 | } 82 | }); 83 | 84 | } 85 | } 86 | -------------------------------------------------------------------------------- /example/src/main/java/com/github/hujiaweibujidao/example/activity/DemoActivity.java: -------------------------------------------------------------------------------- 1 | package com.github.hujiaweibujidao.example.activity; 2 | 3 | import android.animation.TypeEvaluator; 4 | import android.animation.ValueAnimator; 5 | import android.os.Bundle; 6 | import android.support.v7.app.AppCompatActivity; 7 | import android.util.Log; 8 | import android.view.View; 9 | import android.view.animation.Interpolator; 10 | import android.view.animation.LinearInterpolator; 11 | import android.widget.Button; 12 | 13 | import com.github.hujiaweibujidao.example.R; 14 | 15 | /** 16 | * 演示LinearInterpolator和TypeEvaluator 与 TimeInterpolator和LinearEvaluator 的动画效果一样 17 | * 这里使用ValueAnimator来验证 18 | */ 19 | public class DemoActivity extends AppCompatActivity { 20 | 21 | Button buttonStart; 22 | 23 | @Override 24 | protected void onCreate(Bundle savedInstanceState) { 25 | super.onCreate(savedInstanceState); 26 | setContentView(R.layout.activity_demo); 27 | 28 | findViewById(R.id.textview1).setVisibility(View.GONE); 29 | findViewById(R.id.textview2).setVisibility(View.GONE); 30 | findViewById(R.id.buttonStart1).setVisibility(View.GONE); 31 | findViewById(R.id.buttonStart2).setVisibility(View.GONE); 32 | 33 | buttonStart = (Button) findViewById(R.id.buttonStartAll); 34 | buttonStart.setText("Click and see your log"); 35 | 36 | buttonStart.setOnClickListener(new View.OnClickListener() { 37 | @Override 38 | public void onClick(View v) { 39 | ValueAnimator animator1 = new ValueAnimator(); 40 | animator1.setFloatValues(0.0f, 1.0f); 41 | animator1.setDuration(1000); 42 | animator1.setInterpolator(new LinearInterpolator());//传入null也是LinearInterpolator 43 | animator1.setEvaluator(new TypeEvaluator() { 44 | @Override 45 | public Object evaluate(float fraction, Object startValue, Object endValue) { 46 | return 100 * fraction; 47 | } 48 | }); 49 | animator1.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { 50 | @Override 51 | public void onAnimationUpdate(ValueAnimator animation) { 52 | Log.e("demo 1", "" + animation.getAnimatedValue()); 53 | } 54 | }); 55 | 56 | ValueAnimator animator2 = new ValueAnimator(); 57 | animator2.setFloatValues(0.0f, 1.0f); 58 | animator2.setDuration(1000); 59 | animator2.setInterpolator(new Interpolator() { 60 | @Override 61 | public float getInterpolation(float input) { 62 | return 100 * input; 63 | } 64 | }); 65 | animator2.setEvaluator(new TypeEvaluator() { 66 | @Override 67 | public Object evaluate(float fraction, Object startValue, Object endValue) { 68 | return fraction; 69 | } 70 | }); 71 | animator2.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { 72 | @Override 73 | public void onAnimationUpdate(ValueAnimator animation) { 74 | Log.e("demo 2", "" + animation.getAnimatedValue()); 75 | } 76 | }); 77 | 78 | animator1.start(); 79 | animator2.start(); 80 | } 81 | }); 82 | 83 | } 84 | } 85 | -------------------------------------------------------------------------------- /example/src/main/java/com/github/hujiaweibujidao/example/activity/EvaluatorActivity.java: -------------------------------------------------------------------------------- 1 | package com.github.hujiaweibujidao.example.activity; 2 | 3 | import android.animation.ObjectAnimator; 4 | import android.animation.ValueAnimator; 5 | import android.content.Context; 6 | import android.os.Bundle; 7 | import android.support.v7.app.AppCompatActivity; 8 | import android.util.DisplayMetrics; 9 | import android.util.TypedValue; 10 | import android.view.View; 11 | import android.widget.AdapterView; 12 | import android.widget.ListView; 13 | 14 | import com.github.hujiaweibujidao.example.R; 15 | import com.github.hujiaweibujidao.example.adapter.EvaluatorAdapter; 16 | import com.github.hujiaweibujidao.yava.EasingFunction; 17 | import com.github.hujiaweibujidao.example.view.EvaluatorView; 18 | 19 | /** 20 | * 演示TypeEvaluator 21 | */ 22 | public class EvaluatorActivity extends AppCompatActivity { 23 | 24 | private ListView list; 25 | private EvaluatorAdapter adapter; 26 | 27 | private View circle; 28 | private EvaluatorView evaluatorView; 29 | 30 | @Override 31 | protected void onCreate(Bundle savedInstanceState) { 32 | super.onCreate(savedInstanceState); 33 | setContentView(R.layout.activity_evaluator); 34 | 35 | adapter = new EvaluatorAdapter(this); 36 | list = (ListView) findViewById(R.id.list); 37 | list.setAdapter(adapter); 38 | circle = findViewById(R.id.circle); 39 | evaluatorView = (EvaluatorView) findViewById(R.id.drawview); 40 | 41 | list.setOnItemClickListener(new AdapterView.OnItemClickListener() { 42 | @Override 43 | public void onItemClick(AdapterView adapterView, View view, int position, long l) { 44 | evaluatorView.clear(); 45 | circle.setTranslationX(0); 46 | circle.setTranslationY(0); 47 | 48 | ObjectAnimator animator = ObjectAnimator.ofFloat(circle, "translationY", 0, dipToPixels(EvaluatorActivity.this, -(160 - 3))); 49 | animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { 50 | @Override 51 | public void onAnimationUpdate(ValueAnimator animation) { 52 | evaluatorView.drawPoint(animation.getCurrentPlayTime(), animation.getDuration(), (float) animation.getAnimatedValue() - dipToPixels(EvaluatorActivity.this, 60)); 53 | } 54 | }); 55 | animator.setEvaluator(EasingFunction.values()[position]); 56 | animator.setDuration(1200); 57 | animator.start(); 58 | 59 | } 60 | }); 61 | 62 | } 63 | 64 | public static float dipToPixels(Context context, float dipValue) { 65 | DisplayMetrics metrics = context.getResources().getDisplayMetrics(); 66 | return TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dipValue, metrics); 67 | } 68 | 69 | } 70 | -------------------------------------------------------------------------------- /example/src/main/java/com/github/hujiaweibujidao/example/activity/InterpolatorActivity.java: -------------------------------------------------------------------------------- 1 | package com.github.hujiaweibujidao.example.activity; 2 | 3 | import android.os.Bundle; 4 | import android.support.v7.app.AppCompatActivity; 5 | import android.view.View; 6 | import android.view.Window; 7 | import android.widget.AdapterView; 8 | import android.widget.ListView; 9 | 10 | import com.github.hujiaweibujidao.example.R; 11 | import com.github.hujiaweibujidao.example.adapter.InterpolatorAdapter; 12 | 13 | /** 14 | * 演示Interpolator 15 | */ 16 | public class InterpolatorActivity extends AppCompatActivity { 17 | 18 | private static final long DURATION = 2000; 19 | 20 | private ListView listView; 21 | private InterpolatorAdapter adapter; 22 | 23 | @Override 24 | protected void onCreate(Bundle savedInstanceState) { 25 | requestWindowFeature(Window.FEATURE_NO_TITLE); 26 | 27 | super.onCreate(savedInstanceState); 28 | setContentView(R.layout.activity_interpolator); 29 | 30 | adapter = new InterpolatorAdapter(this, DURATION); 31 | listView = (ListView) findViewById(R.id.list); 32 | listView.setAdapter(adapter); 33 | listView.setOnItemClickListener(new AdapterView.OnItemClickListener() { 34 | @Override 35 | public void onItemClick(AdapterView parent, View view, int position, long id) { 36 | adapter.setSelectIndex(position); 37 | } 38 | }); 39 | } 40 | 41 | } 42 | -------------------------------------------------------------------------------- /example/src/main/java/com/github/hujiaweibujidao/example/activity/MainActivity.java: -------------------------------------------------------------------------------- 1 | package com.github.hujiaweibujidao.example.activity; 2 | 3 | import android.content.Intent; 4 | import android.os.Bundle; 5 | import android.support.v7.app.AppCompatActivity; 6 | import android.view.View; 7 | 8 | import com.github.hujiaweibujidao.example.R; 9 | 10 | /** 11 | * 主界面 12 | */ 13 | public class MainActivity extends AppCompatActivity { 14 | 15 | @Override 16 | protected void onCreate(Bundle savedInstanceState) { 17 | super.onCreate(savedInstanceState); 18 | setContentView(R.layout.activity_main); 19 | } 20 | 21 | public void btnInterpolator(View view) { 22 | startActivity(new Intent(this, InterpolatorActivity.class)); 23 | } 24 | 25 | public void btnEvaluator(View view) { 26 | startActivity(new Intent(this, EvaluatorActivity.class)); 27 | } 28 | 29 | public void btnDemo(View view) { 30 | startActivity(new Intent(this, DemoActivity.class)); 31 | } 32 | 33 | public void btnBounce(View view) { 34 | startActivity(new Intent(this, BounceActivity.class)); 35 | } 36 | 37 | public void btnBounce2(View view) { 38 | startActivity(new Intent(this, Bounce2Activity.class)); 39 | } 40 | 41 | public void btnCustom(View view) { 42 | startActivity(new Intent(this, CustomActivity.class)); 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /example/src/main/java/com/github/hujiaweibujidao/example/adapter/EvaluatorAdapter.java: -------------------------------------------------------------------------------- 1 | package com.github.hujiaweibujidao.example.adapter; 2 | 3 | import android.animation.TypeEvaluator; 4 | import android.content.Context; 5 | import android.view.LayoutInflater; 6 | import android.view.View; 7 | import android.view.ViewGroup; 8 | import android.widget.BaseAdapter; 9 | import android.widget.TextView; 10 | 11 | import com.github.hujiaweibujidao.example.R; 12 | import com.github.hujiaweibujidao.yava.EasingFunction; 13 | 14 | import java.util.ArrayList; 15 | import java.util.List; 16 | 17 | /** 18 | * TypeEvaluator list adapter 19 | */ 20 | public class EvaluatorAdapter extends BaseAdapter { 21 | 22 | private LayoutInflater mInflater; 23 | 24 | private List mNames; 25 | private EasingFunction[] mInterpolators; 26 | 27 | public EvaluatorAdapter(Context context) { 28 | mInflater = LayoutInflater.from(context); 29 | 30 | mInterpolators = EasingFunction.values(); 31 | mNames = new ArrayList(); 32 | for (EasingFunction function : EasingFunction.values()) { 33 | mNames.add(function.name()); 34 | } 35 | } 36 | 37 | @Override 38 | public View getView(int position, View convertView, ViewGroup viewGroup) { 39 | ViewHolder mHolder = null; 40 | if (convertView == null) { 41 | mHolder = new ViewHolder(); 42 | convertView = mInflater.inflate(R.layout.item, null); 43 | mHolder.textView = (TextView) convertView.findViewById(R.id.list_item_text); 44 | convertView.setTag(mHolder); 45 | } else { 46 | mHolder = (ViewHolder) convertView.getTag(); 47 | } 48 | 49 | TypeEvaluator evaluator = mInterpolators[position]; 50 | mHolder.textView.setText(String.format("%s Evaluator", mNames.get(position).replace("_", " "))); 51 | //convertView.setTag(o);// 52 | return convertView; 53 | } 54 | 55 | private class ViewHolder { 56 | public TextView textView; 57 | } 58 | 59 | @Override 60 | public int getCount() { 61 | return mInterpolators == null ? 0 : mInterpolators.length; 62 | } 63 | 64 | @Override 65 | public Object getItem(int position) { 66 | return mInterpolators == null ? null : mInterpolators[position]; 67 | } 68 | 69 | @Override 70 | public long getItemId(int position) { 71 | return position; 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /example/src/main/java/com/github/hujiaweibujidao/example/adapter/InterpolatorAdapter.java: -------------------------------------------------------------------------------- 1 | package com.github.hujiaweibujidao.example.adapter; 2 | 3 | import android.content.Context; 4 | import android.view.LayoutInflater; 5 | import android.view.View; 6 | import android.view.ViewGroup; 7 | import android.view.animation.Animation; 8 | import android.view.animation.Interpolator; 9 | import android.view.animation.TranslateAnimation; 10 | import android.widget.BaseAdapter; 11 | import android.widget.RelativeLayout; 12 | import android.widget.RelativeLayout.LayoutParams; 13 | import android.widget.TextView; 14 | 15 | import com.github.hujiaweibujidao.example.R; 16 | import com.github.hujiaweibujidao.yava.EasingFunction; 17 | import com.github.hujiaweibujidao.example.view.CursorView; 18 | import com.github.hujiaweibujidao.example.view.InterpolatorView; 19 | 20 | import java.util.ArrayList; 21 | import java.util.List; 22 | 23 | /** 24 | * Interpolator list adapter 25 | *

26 | */ 27 | public class InterpolatorAdapter extends BaseAdapter { 28 | 29 | private int mSelectIndex = -1; 30 | private long mDuration; 31 | private LayoutInflater mInflater; 32 | private List mNames; 33 | private EasingFunction[] mInterpolators; 34 | 35 | public InterpolatorAdapter(Context context, long duration) { 36 | mInflater = LayoutInflater.from(context); 37 | mDuration = duration; 38 | 39 | mInterpolators = EasingFunction.values(); 40 | mNames = new ArrayList(); 41 | for (EasingFunction function : EasingFunction.values()) { 42 | mNames.add(function.name()); 43 | } 44 | } 45 | 46 | @Override 47 | public View getView(int position, View convertView, ViewGroup parent) { 48 | ViewHolder mHolder = null; 49 | if (convertView == null) { 50 | mHolder = new ViewHolder(); 51 | convertView = mInflater.inflate(R.layout.adapter, null); 52 | mHolder.interpolatorName = (TextView) convertView.findViewById(R.id.name); 53 | mHolder.interpolatorView = (InterpolatorView) convertView.findViewById(R.id.view); 54 | mHolder.cursor = (CursorView) convertView.findViewById(R.id.cursor); 55 | convertView.setTag(mHolder); 56 | } else { 57 | mHolder = (ViewHolder) convertView.getTag(); 58 | } 59 | 60 | final Interpolator interpolator = mInterpolators[position]; 61 | mHolder.interpolatorName.setText(String.format("%s Interpolator", mNames.get(position).replace("_", " "))); 62 | mHolder.interpolatorView.setDurationAndInterpolator(mDuration, interpolator);// 63 | 64 | int bottomMargin = mHolder.interpolatorView.blankTB - mHolder.cursor.height / 2; 65 | LayoutParams params = (LayoutParams) mHolder.cursor.getLayoutParams(); 66 | params.addRule(RelativeLayout.ALIGN_BOTTOM, R.id.view); 67 | params.bottomMargin = bottomMargin; 68 | mHolder.cursor.setLayoutParams(params); 69 | 70 | //选定项开始做Ease动画,这里操控cursorview使用的只是普通的位移动画而已 71 | if (position == mSelectIndex) { 72 | int toYDelta = mHolder.interpolatorView.height - 2 * mHolder.interpolatorView.blankTB; 73 | Animation anim = new TranslateAnimation(0, 0, 0, -toYDelta); 74 | anim.setDuration(mDuration); 75 | anim.setInterpolator(interpolator); 76 | anim.setStartOffset(300); 77 | mHolder.cursor.startAnimation(anim); 78 | mSelectIndex = -1; 79 | } 80 | 81 | return convertView; 82 | } 83 | 84 | public void setSelectIndex(int index) { 85 | mSelectIndex = index; 86 | notifyDataSetChanged(); 87 | } 88 | 89 | private class ViewHolder { 90 | public TextView interpolatorName; 91 | public InterpolatorView interpolatorView; 92 | public CursorView cursor; 93 | } 94 | 95 | @Override 96 | public int getCount() { 97 | return mInterpolators == null ? 0 : mInterpolators.length; 98 | } 99 | 100 | @Override 101 | public Object getItem(int position) { 102 | return mInterpolators == null ? null : mInterpolators[position]; 103 | } 104 | 105 | @Override 106 | public long getItemId(int position) { 107 | return position; 108 | } 109 | 110 | } -------------------------------------------------------------------------------- /example/src/main/java/com/github/hujiaweibujidao/example/view/CursorView.java: -------------------------------------------------------------------------------- 1 | package com.github.hujiaweibujidao.example.view; 2 | 3 | import android.content.Context; 4 | import android.graphics.Canvas; 5 | import android.graphics.Color; 6 | import android.graphics.Paint; 7 | import android.graphics.Path; 8 | import android.util.AttributeSet; 9 | import android.view.View; 10 | 11 | /** 12 | * 指示器 13 | *

14 | * Created by cimi on 15/7/6. 15 | */ 16 | public class CursorView extends View { 17 | 18 | public int width; 19 | public int height; 20 | 21 | private Context context; 22 | private Paint paint; 23 | private Path path; 24 | 25 | public CursorView(Context context) { 26 | this(context, null); 27 | } 28 | 29 | public CursorView(Context context, AttributeSet attrs) { 30 | super(context, attrs); 31 | this.context = context; 32 | init(); 33 | } 34 | 35 | private void init() { 36 | width = dip2px(20); //from layout 37 | height = dip2px(8); //from layout 38 | 39 | paint = new Paint(); 40 | paint.setAntiAlias(true); 41 | paint.setStrokeWidth(1); 42 | paint.setStyle(Paint.Style.FILL); 43 | paint.setColor(Color.RED); 44 | 45 | path = new Path(); 46 | path.moveTo(0, height / 2); 47 | path.lineTo(width / 5, 0); 48 | path.lineTo(width, 0); 49 | path.lineTo(width, height); 50 | path.lineTo(width / 5, height); 51 | path.close(); 52 | } 53 | 54 | @Override 55 | protected void onDraw(Canvas canvas) { 56 | super.onDraw(canvas); 57 | canvas.drawPath(path, paint); 58 | } 59 | 60 | private int dip2px(float dpValue) { 61 | final float scale = context.getResources() 62 | .getDisplayMetrics().density; 63 | return (int) (dpValue * scale + 0.5f); 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /example/src/main/java/com/github/hujiaweibujidao/example/view/EvaluatorView.java: -------------------------------------------------------------------------------- 1 | /* 2 | * 3 | * * The MIT License (MIT) 4 | * * 5 | * * Copyright (c) 2014 daimajia 6 | * * 7 | * * Permission is hereby granted, free of charge, to any person obtaining a copy 8 | * * of this software and associated documentation files (the "Software"), to deal 9 | * * in the Software without restriction, including without limitation the rights 10 | * * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | * * copies of the Software, and to permit persons to whom the Software is 12 | * * furnished to do so, subject to the following conditions: 13 | * * 14 | * * The above copyright notice and this permission notice shall be included in all 15 | * * copies or substantial portions of the Software. 16 | * * 17 | * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | * * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | * * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | * * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | * * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | * * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23 | * * SOFTWARE. 24 | * 25 | */ 26 | 27 | package com.github.hujiaweibujidao.example.view; 28 | 29 | import android.content.Context; 30 | import android.graphics.Canvas; 31 | import android.graphics.Color; 32 | import android.graphics.Paint; 33 | import android.graphics.Path; 34 | import android.util.AttributeSet; 35 | import android.util.DisplayMetrics; 36 | import android.util.TypedValue; 37 | import android.view.View; 38 | 39 | import java.util.ArrayList; 40 | 41 | /** 42 | * 绘制TypeEvaluator的View 43 | */ 44 | public class EvaluatorView extends View { 45 | 46 | private Paint mBackgroundPaint = new Paint(); 47 | private Paint mLinePaint = new Paint(); 48 | private Path path = new Path(); 49 | private boolean start = false; 50 | 51 | private ArrayList mHistory = new ArrayList(); 52 | 53 | { 54 | mBackgroundPaint.setColor(Color.WHITE); 55 | mLinePaint.setColor(Color.rgb(77, 83, 96)); 56 | mLinePaint.setAntiAlias(true); 57 | mLinePaint.setStrokeWidth((float) 3.0); 58 | mLinePaint.setStyle(Paint.Style.STROKE); 59 | } 60 | 61 | public EvaluatorView(Context context) { 62 | super(context); 63 | } 64 | 65 | public EvaluatorView(Context context, AttributeSet attrs) { 66 | super(context, attrs); 67 | } 68 | 69 | public EvaluatorView(Context context, AttributeSet attrs, int defStyleAttr) { 70 | super(context, attrs, defStyleAttr); 71 | } 72 | 73 | @Override 74 | protected void onDraw(Canvas canvas) { 75 | super.onDraw(canvas); 76 | float l = 0; 77 | float t = getHeight() - getPaddingBottom() - dipToPixels(getContext(), 217); 78 | float r = getWidth() - getPaddingRight(); 79 | float b = getHeight() - dipToPixels(getContext(), 60); 80 | canvas.drawRect(l, t, r, b, mLinePaint); 81 | canvas.drawPath(path, mLinePaint); 82 | } 83 | 84 | public static float dipToPixels(Context context, float dipValue) { 85 | DisplayMetrics metrics = context.getResources().getDisplayMetrics(); 86 | return TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dipValue, metrics); 87 | } 88 | 89 | public void drawPoint(float time, float duration, float y) { 90 | float p = time / duration; 91 | float x = p * getWidth(); 92 | float z = getHeight() + y; 93 | if (!start) { 94 | path.moveTo(x, z); 95 | start = true; 96 | } 97 | path.lineTo(x, z); 98 | invalidate(); 99 | } 100 | 101 | public void clear() { 102 | path.reset(); 103 | start = false; 104 | invalidate(); 105 | } 106 | 107 | } 108 | -------------------------------------------------------------------------------- /example/src/main/java/com/github/hujiaweibujidao/example/view/InterpolatorView.java: -------------------------------------------------------------------------------- 1 | package com.github.hujiaweibujidao.example.view; 2 | 3 | import android.content.Context; 4 | import android.graphics.Canvas; 5 | import android.graphics.Color; 6 | import android.graphics.Paint; 7 | import android.graphics.Path; 8 | import android.util.AttributeSet; 9 | import android.view.View; 10 | import android.view.animation.Interpolator; 11 | 12 | /** 13 | * 函数曲线图 14 | *

15 | * Created by cimi on 15/7/6. 16 | */ 17 | public class InterpolatorView extends View { 18 | 19 | public int width; 20 | public int height; 21 | public int blankTB;//blank of top or bottom 22 | public int blankLR;//blank of left or right 23 | 24 | private Context context; 25 | private Paint linePaint; 26 | private Paint pathPaint; 27 | private Path path; 28 | 29 | public InterpolatorView(Context context) { 30 | this(context, null); 31 | } 32 | 33 | public InterpolatorView(Context context, AttributeSet attrs) { 34 | super(context, attrs); 35 | this.context = context; 36 | init(); 37 | } 38 | 39 | private void init() { 40 | width = dip2px(100); //from layout, 100dp 41 | height = dip2px(100); //from layout 42 | blankTB = height * 2 / 7;//why? 43 | blankLR = 0; 44 | 45 | linePaint = new Paint(); 46 | linePaint.setAntiAlias(true); 47 | linePaint.setStrokeWidth(1); 48 | linePaint.setStyle(Paint.Style.STROKE); 49 | linePaint.setColor(Color.DKGRAY); 50 | 51 | pathPaint = new Paint(); 52 | pathPaint.setAntiAlias(true); 53 | pathPaint.setStrokeWidth(2); 54 | pathPaint.setStyle(Paint.Style.STROKE); 55 | pathPaint.setColor(Color.RED); 56 | 57 | path = new Path(); 58 | } 59 | 60 | public void setDurationAndInterpolator(long duration, Interpolator interpolator) { 61 | if (duration <= 0) 62 | return; 63 | if (interpolator == null) 64 | return; 65 | 66 | int w = width - blankLR * 2; 67 | int h = height - blankTB * 2; 68 | 69 | path.reset(); 70 | path.moveTo(blankLR, height - blankTB); 71 | int factor = (int) (duration / w + (duration % w > 0 ? 1 : 0)); 72 | int i = 0; 73 | for (; i < duration; i += factor) { 74 | path.lineTo(i / factor + blankLR, h - interpolator.getInterpolation((float) i / duration) * h + blankTB); 75 | } 76 | 77 | // if (!(interpolator instanceof EaseBreathInterpolator)) 78 | // path.lineTo(i / factor + blankLR, blankTB); 79 | 80 | invalidate(); 81 | } 82 | 83 | @Override 84 | protected void onDraw(Canvas canvas) { 85 | canvas.drawLine(0, blankTB, width, blankTB, linePaint);//float startX, float startY, float stopX, float stopY, Paint paint 86 | canvas.drawLine(0, height - blankTB, width, height - blankTB, linePaint); 87 | 88 | canvas.drawPath(path, pathPaint); 89 | } 90 | 91 | private int dip2px(float dpValue) { 92 | final float scale = context.getResources().getDisplayMetrics().density; 93 | return (int) (dpValue * scale + 0.5f); 94 | } 95 | } 96 | -------------------------------------------------------------------------------- /example/src/main/res/drawable/circle.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /example/src/main/res/layout/activity_demo.xml: -------------------------------------------------------------------------------- 1 | 2 | 12 | 13 | 19 | 20 | 29 | 30 | 40 | 41 | 42 | 43 | 49 | 50 |