文章内容
- 逐帧动画
- 视图动画系统
- 属性动画系统
-
动画的种类
分类转:https://blog.csdn.net/pzm1993/article/details/77167049
-
Android的动画可以分为以下3种:
- 图片动画
图片动画,其实也是逐帧动画,是通过一个接一个的加载绘制对象资源来创建动画,按顺序的播放,像一个胶卷。对于视图动画,他只是单独的图片内容在变换,而不是整个视图。很显然,如果图片过多多大就会导致OOM异常。
- View动画
视图动画,通多对整个视图不断做图像的变换(平移,缩放,旋转,透明度)产生的动画效果,是一种渐进式动画。
其中观看动画又可以分为:补间动画和逐动动画
- 属性动画
属性动画,在Android 3.0的(API级别11)引入的,该属性动画系统可以制作动画的任何对象的属性。但是一般来说,属性动画系统是首选的使用方法,因为它更灵活,并提供更多功能。
一,逐帧动画
由多个图像组成的自定义加载动画,每一张图片作为动画的一帧,当顺序执行并给它一定时间间隔展示就形成一种动画的效果
使用AnimationDrawable
定义转:https://www.jianshu.com/p/ce5014c4bc95
的动画一种方法Drawables
的英文逐个加载一系列柯林斯绘制资源来创建³³动画。这是一个传统的动画,它是由一系列不同的图像创建的,按照顺序播放,就像一卷电影一样。本。AnimationDrawable
类的英文柯林斯绘制动画的基础。
虽然您可以使用AnimationDrawable
类API在代码中定义动画的框架,但使用列出组成动画的框架的单个XML文件更简单。这种动画的XML文件属于res/drawable/
您的Android项目的目录。在这种情况下,指令的英文动画每帧的顺序状语从句:持续时间。
它的实际相当于装绘制的一种容器,来控制绘制的显示
具体使用:
1,我们准备了三张图片:frame1,2,3来当做这个动画的三帧
2,新建工程,在将图片放到drawable文件夹下,并在drawable文件下(右键new)创建一个drawable资源文件文件
3,(frameanimation.xml)XML由文件一个元素作为根节点状语从句:一系列子节点组成<animation-list>
<item>
- 每一个项目对应一帧
- 持续时间:该帧持续的时间
- 绘制:该帧对应的图片
<?xml version="1.0" encoding="utf-8"?>
<animation-list xmlns:android="http://schemas.android.com/apk/res/android">
<!--第一帧-->
<item android:drawable="@drawable/frame_1" android:duration="100" />
<!--第二帧-->
<item android:drawable="@drawable/frame_2" android:duration="100" />
<!--第三帧-->
<item android:drawable="@drawable/frame_3" android:duration="100" />
</animation-list>
4,创建视图展示动画activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".FrameAnimationActivity">
<!--将动画视图放在这个view中展示-->
<View
android:id="@+id/frame_animation"
android:layout_width="300dp"
android:layout_height="300dp"
android:layout_centerHorizontal="true"
android:layout_centerVertical="true"
android:background="@drawable/framanimation" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:orientation="horizontal">
<Button
android:id="@+id/btnStart"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:onClick="onClick"
android:text="Start" />
<Button
android:id="@+id/btnStop"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:onClick="onClick"
android:text="Stop" />
<Button
android:id="@+id/btnOneShot"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:onClick="onClick"
android:text="OneShot" />
</LinearLayout>
</RelativeLayout>
5.FrameAnimationActivity.java实现动画效果
重要的三个属性:
- 开始(); 开启动画
- 停止();停止动画
- setOneShot(boolean b);让动画执行一次
import android.graphics.drawable.AnimationDrawable;
import android.graphics.drawable.Drawable;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
public class FrameAnimationActivity extends AppCompatActivity {
private View mAnimationView;
private AnimationDrawable animationDrawable;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//初始化视图
mAnimationView = findViewById(R.id.frame_animation);
//拿到视图的背景,也就是之前定义的drawable 强转为AnimationDrawable
animationDrawable = (AnimationDrawable) mAnimationView.getBackground();
}
public void onClick(View view) {
switch (view.getId()) {
case R.id.btnStart:
animationDrawable.start();
break;
case R.id.btnStop:
animationDrawable.stop();
break;
case R.id.btnOneShot:
//默认每一帧都是无限循环的
//可以通过这个属性设置只执行一轮
animationDrawable.setOneShot(true);
break;
}
}
}
效果:
二,视图动画系统(View animation)
视图动画的作用对象只能是查看,同在一个图形通过在界面上进行透明度,缩放,旋转,平移的变化。
查看动画的分类:
view动画支持4中动画效果,分别是:
- 透明度动画(AlphaAnimation)
- 缩放动画(ScaleAnimation)
- 平移动画(TranslateAnimation)
- 旋转动画(RotateAnimation)
- 集合动画(AnimationSet)
不同动画与Java类、xml文件关键字对应关系如下:转:https://www.jianshu.com/p/26a801a755a0
名称 | Java子类 | xml关键字 | 说明 |
---|---|---|---|
透明度动画 | AlphaAnimation | <alpha> 放置在res/anim/ 目录下 | 透明度渐变 |
旋转动画 | RotateAnimation | <rotate> 放置在res/anim/ 目录下 | 视图旋转 |
缩放动画 | ScaleAnimation | <scale> 放置在res/anim/ 目录下 | 放大/缩小 视图尺寸大小 |
平移动画 | TranslateAnimation | <translate> 放置在res/anim/ 目录下 | 视图位置移动 |
复合动画 | AnimationSet | <set> 放置在res/anim/ 目录下 | 一个持有其它动画元素alpha、scale、translate、rotate或者其它set元素的容器 |
如图所示,图中几个类多是Animation的子类,在java代码中具体实现也是通过这些子类来实现
由于Animation
是抽象基类,其提供了一些通用的动画属性方法,如下所示
xml属性 | Java方法 | 说明 |
---|---|---|
android:detachWallpaper | setDetachWallpaper(boolean) | 是否在壁纸上运行 |
android:duration | setDuration(long) | 动画的运行时间(以毫秒为单位);必须设置 |
android:fillAfter | setFillAfter(boolean) | 动画结束时是否保持动画最后的状态;默认为false,优先于fillBefore |
android:fillBefore | setFillBefore(boolean) | 动画结束时是否还原到开始动画前的状态;默认为true |
android:fillEnabled | setFillEnabled(boolean) | 是否应用fillBefore的值,对fillAfter无影响;默认为true |
android:interpolator | setInterpolator(Interpolator) | 设定插值器(指定的动画效果,譬如回弹等) |
android:repeatCount | setRepeatCount(int) | 重复次数 |
android:repeatMode | setRepeatMode(int) | 重复类型有两个值,reverse表示倒序回放,restart表示从头播放 |
android:startOffset | setStartOffset(long) | 调用start函数之后等待开始运行的时间,单位为毫秒 |
android:zAdjustment | setZAdjustment(int) | 表示被设置动画的内容运行时在Z轴上的位置(top/bottom/normal),默认为normal |
这4种动画既能分开独立实现,也可以组合实现复合动画AnimationSet。如果这些动画还是满足不了你,可以自定义动画。不过,后面有了属性动画之后,大部分还是可以满足需求。
view动画的实现可以通过Xml来定义,也可以通过java代码来动态设置。对于view动画,建议使用XML来定义动画,可读性好,而且能过复用。而对于属性动画,则建议是通过代码动态设置,后文会介绍。
一、透明度动画(AlphaAnimation)
控制视图的透明度
透明度动画(Alpha)-- 属性
xml属性 | Java方法 | 说明 |
---|---|---|
android:fromAlpha | AlphaAnimation(float fromAlpha, …) | 动画开始的透明度(0.0到1.0,0.0是全透明,1.0是不透明) |
android:toAlpha | AlphaAnimation(…, float toAlpha) | 动画结束的透明度,同上 |
步骤:
1、在res目录下创建anim文件夹 新建一个xml文件 使用<alpha> 标签这里命名为:alpha_animation.xml
<?xml version="1.0" encoding="utf-8"?>
<!--放在set动画集合中-->
<set android:duration="1000" xmlns:android="http://schemas.android.com/apk/res/android">
<!--fromAlpha 开始的透明度 0.0->1.0 从全透明到不透明 1.0代表完全不透明-->
<alpha
android:fromAlpha="1.0"
android:toAlpha="0.1" />
</set>
2、创建显示动画的布局 这里以TextView为这个视图 这里是:viewanimation.xml
<?xml version="1.0" encoding="utf-8"?>
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<TextView
android:id="@+id/tv_alpha"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@color/colorPrimaryDark"
android:padding="20dp"
android:onClick="onClick"
android:text="alpha"
android:textAppearance="@style/TextAppearance.AppCompat.Large"
android:textColor="#ffffff"
android:textSize="30sp" />
</LinearLayout>
</ScrollView>
3.java代码实现 实现点击textView 透明度发生变化的效果
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.view.animation.Animation;
import android.view.animation.AnimationUtils;
import com.demo.android4step1.R;
/**
* <p>文件描述:<p>
* <p>作者:Mr-Donkey<p>
* <p>创建时间:2018/12/9 16:40<p>
* <p>更改时间:2018/12/9 16:40<p>
* <p>版本号:1<p>
*/
public class AlphaAnimationActivity extends AppCompatActivity {
private Animation animation;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.viewanimation);
}
public void onClick(View view) {
switch (view.getId()) {
case R.id.tv_alpha:
//加载动画拿到 animation对象
animation = AnimationUtils.loadAnimation(this, R.anim.alpha_animation);
//通过此时的view设置动画
view.startAnimation(animation);
break;
}
}
}
效果:
二、缩放动画(ScaleAnimation)
控制每一个视图的X、Y轴的缩放程度
缩放动画(Scale)-- 属性
xml属性 | Java方法 | 说明 |
---|---|---|
android:fromXScale | ScaleAnimation(float fromX, …) | 初始X轴缩放比例,1.0表示无变化 |
android:toXScale | ScaleAnimation(…, float toX, …) | 结束X轴缩放比例 |
android:fromYScale | ScaleAnimation(…, float fromY, …) | 初始Y轴缩放比例 |
android:toYScale | ScaleAnimation(…, float toY, …) | 结束Y轴缩放比例 |
android:pivotX | ScaleAnimation(…, float pivotX, …) | (基准点)缩放起点X轴坐标(数值、百分数、百分数p,譬如50表示以当前View左上角坐标加50px为初始点、50%表示以当前View的左上角加上当前View宽高的50%做为初始点、50%p表示以当前View的左上角以父控件宽度的50%做为初始点) |
android:pivotY | ScaleAnimation(…, float pivotY) | (基准点)缩放起点Y轴坐标,同上规律 |
实现步骤:
1、在上面anim文件夹中新建xml文件 使用<scale>标签 这里命名为:
<?xml version="1.0" encoding="utf-8"?>
<!--duration:动画间隔 fillAfter:保持最后的状态,不恢复原来的状态 -->
<set xmlns:android="http://schemas.android.com/apk/res/android"
android:duration="1000"
android:fillAfter="true"
>
<!--X轴初始值from为原来的宽度,结束后to变成原来的2倍宽度-->
<!--Y轴不变-->
<scale
android:fromXScale="1.0"
android:toXScale="2.0"
android:fromYScale="1.0"
android:toYScale="1.0">
</scale>
</set>
2、在上面的布局viewanimation.xml中
将textView的部分属性抽取出来(如果有多个view共用的话,抽取style)
进入布局文件 点击Refactor——>Extract——>Style
提取共用的部分作为style,方便以后的视图使用,就不用重复写这么多次了
此时textView就可以用一个style 包含之前的属性
<TextView
android:id="@+id/tv_alpha"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:onClick="onClick"
android:text="alpha"
style="@style/AnimationTextView" />
然后再添加一个 TextView 在alpha的下面
<!--这是Scale动画的视图-->
<TextView
android:id="@+id/tv_scale"
style="@style/AnimationTextView"
android:layout_marginTop="10dp"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:onClick="onClick"
android:text="scale" />
3.java 代码实现 在OnClick函数添加
case R.id.tv_scale:
//加载动画拿到 animation对象
animation = AnimationUtils.loadAnimation(this, R.anim.scale_animation);
view.startAnimation(animation);
break;
效果:
sacle的基准点属性
android:pivotX | ScaleAnimation(…, float pivotX, …) | (基准点)缩放起点X轴坐标(数值、百分数、百分数p,譬如50表示以当前View左上角坐标加50px为初始点、50%表示以当前View的左上角加上当前View宽高的50%做为初始点、50%p表示以当前View的左上角加上父控件宽高的50%做为初始点) |
android:pivotY | ScaleAnimation(…, float pivotY) | (基准点)缩放起点Y轴坐标,同上规律 |
修改一下上面代码:
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
android:duration="1000"
android:fillAfter="true"
>
<!--X轴初始值from为原来的宽度,结束后to变成原来的2倍宽度-->
<!--Y轴也一样-->
<scale
android:fromXScale="1.0"
android:toXScale="2.0"
android:fromYScale="1.0"
android:toYScale="2.0"
android:pivotX="50%"
android:pivotY="50%">
</scale>
</set>
让视图居中
<!--这是Scale动画的视图-->
<TextView
android:id="@+id/tv_scale"
style="@style/AnimationTextView"
android:layout_marginTop="10dp"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:onClick="onClick"
android:layout_gravity="center_horizontal"
android:text="scale" />
效果:以视图的X、Y周轴中心作为基准点,放大两被的效果
三、平移动画(TranslateAnimation)
平移动画(Translate)-- 属性
xml属性 | Java方法 | 说明 |
---|---|---|
android:fromXDelta | TranslateAnimation(float fromXDelta, …) | 起始点X轴坐标(数值、百分数、百分数p,譬如50表示以当前View左上角坐标加50px为初始点、50%表示以当前View的左上角加上当前View宽高的50%做为初始点、50%p表示以当前View的左上角加上父控件宽高的50%做为初始点) |
android:fromYDelta | TranslateAnimation(…, float fromYDelta, …) | 起始点Y轴从标,同上规律 |
android:toXDelta | TranslateAnimation(…, float toXDelta, …) | 结束点X轴坐标,同上规律 |
android:toYDelta | TranslateAnimation(…, float toYDelta) | 结束点Y轴坐标,同上规律 |
步骤:
1、anim文件夹中创建 xml文件
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
android:duration="1000"
android:fillAfter="true"
>
<!--fromXDelta 开始X轴的偏移 toXDelta 目的地的偏移 50% 为控件的宽度的50%-->
<!--Y轴同理-->
<translate
android:fromXDelta="0"
android:fromYDelta="0"
android:toXDelta="50%"
android:toYDelta="0">
</translate>
</set>
2、给布局中添加视图(省略了)
3、java代码的实现
case R.id.tv_translate:
//加载动画拿到 animation对象
animation = AnimationUtils.loadAnimation(this, R.anim.translate_animation);
view.startAnimation(animation);
break;
效果:
android:repeatCount | setRepeatCount(int) | 重复次数 |
android:repeatMode | setRepeatMode(int) | 重复类型有两个值,reverse表示倒序回放,restart表示从头播放 |
两种重复模式 :restart 重头开始 reverse 原路返回
1、重头开始 restart
android:repeatMode="restart"
android:repeatCount="1"
2、原路返回 reverse
四、旋转动画(RotateAnimation)
旋转动画(Rotate)-- 属性
xml属性 | Java方法 | 说明 |
---|---|---|
android:fromDegrees | RotateAnimation(float fromDegrees, …) | 旋转开始角度,正代表顺时针度数,负代表逆时针度数 |
android:toDegrees | RotateAnimation(…, float toDegrees, …) | 旋转结束角度,正代表顺时针度数,负代表逆时针度数 |
android:pivotX | RotateAnimation(…, float pivotX, …) | 缩放起点X坐标(数值、百分数、百分数p,譬如50表示以当前View左上角坐标加50px为初始点、50%表示以当前View的左上角加上当前View宽高的50%做为初始点、50%p表示以当前View的左上角加上父控件宽高的50%做为初始点) |
android:pivotY | RotateAnimation(…, float pivotY) | 缩放起点Y坐标,同上规律 |
步骤:同理 anim文件夹中创建xml文件
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
android:duration="1000"
android:fillAfter="true"
>
<!--开始角度为0 即正常的样子 结束角度
90度 则发生偏转90 正数顺时针 负数逆时针-->
<rotate
android:fromDegrees="0"
android:toDegrees="90">
</rotate>
</set>
布局添加一个视图作为旋转动画的视图
<!--这是rotate动画的视图-->
<TextView
android:id="@+id/tv_rotate"
style="@style/AnimationTextView"
android:layout_marginTop="10dp"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:onClick="onClick"
android:gravity="center"
android:layout_gravity="center_horizontal"
android:text="rotate" />
<!--如果视图显示不全 可以再下方加一个空白的View-->
<View
android:layout_width="match_parent"
android:layout_height="300dp"/>
3.java代码中添加一个点击事件
case R.id.tv_rotate:
//加载动画拿到 animation对象
animation = AnimationUtils.loadAnimation(this, R.anim.rotate_animation);
view.startAnimation(animation);
break;
效果: 如果需要改基准点可以设置 pivot 属性
五、集合动画(AnimationSet)
一个持有其它动画元素alpha、scale、translate、rotate或者其它set元素的容器
将上述四种动画结合起来显示
例子1:anim文件夹中创建 set.xml 包含旋转和平移动画
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
<!--旋转动画-->
<rotate
android:duration="1000"
android:fromDegrees="0"
android:pivotX="50%"
android:pivotY="50%"
android:toDegrees="720" />
<!--位移动画-->
<translate
android:duration="1000"
android:fromXDelta="0"
android:fromYDelta="0"
android:toXDelta="500"
android:toYDelta="0" />
</set>
2.添加视图(略)
3.添加点击事件(略)
效果
android:startOffset | setStartOffset(long) | 调用start函数之后等待开始运行的时间,单位为毫秒 |
startOffset 函数可以这是等待多少时间之后再运行当前这个动画
拿上面的例子,让它先旋转完成再进行平移
<!--位移动画-->
<translate
android:duration="1000"
android:startOffset="1000"
android:fromXDelta="0"
android:fromYDelta="0"
android:toXDelta="500"
android:toYDelta="0" />
效果:
Animation
还有如下一些比较实用的方法介绍:
Animation类的方法 | 解释 |
---|---|
reset() | 重置Animation的初始化 |
cancel() | 取消Animation动画 |
start() | 开始Animation动画 |
hasStarted() | 判断当前Animation是否开始 |
hasEnded() | 判断当前Animation是否结束 |
既然补间动画只能给View
使用,那就来看看View
中和动画相关的几个常用方法吧,如下:
View类的常用动画操作方法 | 解释 |
---|---|
startAnimation(Animation animation) | 对当前View开始设置的Animation动画 |
clearAnimation() | 取消当View在执行的Animation动画 |
特别特别注意:视图动画执行之后并未改变View的真实布局属性值。切记这一点,譬如我们在Activity中有一个Button在屏幕上方,我们设置了平移动画移动到屏幕下方然后保持动画最后执行状态呆在屏幕下方,这时如果点击屏幕下方动画执行之后的Button是没有任何反应的,而点击原来屏幕上方没有Button的地方却响应的是点击Button的事件。
动画监听
- 动画监听器接收来自动画的通知。通知表示与动画相关的事件,例如动画的结束或重复
- 使用方法:
Animation.addListener(new AnimatorListener() {
@Override
public void onAnimationStart(Animation animation) {
//动画开始时执行
}
@Override
public void onAnimationRepeat(Animation animation) {
//动画重复时执行
}
@Override
public void onAnimationCancel()(Animation animation) {
//动画取消时执行
}
@Override
public void onAnimationEnd(Animation animation) {
//动画结束时执行
}
});
- 视图动画的监听只能通过此方式,且必须要复写全部4个方法。
- 属性动画时,可以采用
Animator.addListener(new AnimatorListenerAdapter(){ //复写指定方法 })
------动画适配器AnimatorListenerAdapter中已经实现好每个接口
视图动画-插值器(Interpolator)
插值器是在XML中定义的一个动画修改器,它影响动画的变化率。这允许现有动画附加加速、减速、重复、反弹等效果。
继承关系
系统为我们提供了上图中的各种插值器,其都是实现了Interpolator接口的实现类,具体说明如下:
java类 | XML 资源ID | 说明 |
---|---|---|
AccelerateDecelerateInterpolator | @android:anim/accelerate_decelerate_interpolator | 先加速再减速 |
AccelerateInterpolator | @android:anim/accelerate_interpolator | 持续加速 |
AnticipateInterpolator | @android:anim/anticipate_interpolator | 先退后再加速前进 |
AnticipateOvershootInterpolator | @android:anim/anticipate_overshoot_interpolator | 先退后再加速前进,超出终点后再回终点 |
BounceInterpolator | @android:anim/bounce_interpolator | 结束时弹球效果 |
CycleInterpolator | @android:anim/cycle_interpolator | 周期运动 |
DecelerateInterpolator | @android:anim/decelerate_interpolator | 减速 |
LinearInterpolator | @android:anim/linear_interpolator | 匀速 |
OvershootInterpolator | @android:anim/overshoot_interpolator | 向前弹出一定值之后回到原来位置(快速完成动画,超出再回到结束样式) |
使用方法
- XML方式
<set android:interpolator="@android:anim/accelerate_interpolator">
...
</set>
- JAVA方式 使用不同的速率 直接new上面给出的类就行了 android定义好的
//加载动画拿到 animation对象
animation = AnimationUtils.loadAnimation(this, R.anim.translate_animation);
//创建插值器对象
Interpolator interpolator = new OvershootInterpolator();
//为动画添加插值器
view.setInterpolator(interpolator);
view.startAnimation(animation);
给动画多添加了一个插值器
自定义插值器
某些情景可能你会发现系统提供的插值器不能满足需求,此时我们需要自定义插值器。有两种实现方式:
XML自定义实现 和 JAVA代码实现方式
XML实现
- 在
res/anim/
下创建filename.xml
- 修改插值器属性(如下不作任何修改,则与系统预设插值器功能相同)
<?xml version="1.0" encoding="utf-8"?>
<InterpolatorName xmlns:android="http://schemas.android.com/apk/res/android"
android:attribute_name="value"
/>
- 视图动画中引用该文件(资源引用为
@[package:]anim/filename
)
XML实现方式本质就是修改系统提供的插值器的某些属性,具体可修改属性如下:
插值器 | 可修改属性 | 属性说明 |
---|---|---|
<accelerateDecelerateInterpolator> | 无属性 | |
<accelerateInterpolator> | android:factor | Float,加速速率(默认值为1) |
<anticipateInterpolator> | android:tension | Float. 起始点后拉的张力数(默认值为2) |
<anticipateOvershootInterpolator> | android:tension android:extraTension | Float. 起始点后拉的张力数(默认值为2) Float. 拉力的倍数(默认值为1.5) |
<bounceInterpolator> | 无属性 | |
<cycleInterpolator> | android:cycles | Integer. 循环次数(默认为1) |
<decelerateInterpolator> | android:factor | Float. 减速的速率(默认为1) |
<linearInterpolator> | 无属性 | |
<overshootInterpolator> | android:tension | Float. 超出终点后的张力(默认为2) |
JAVA方式
在此只讨论原理,不设计具体逻辑(奈何我是个数学渣,公式真的是一头雾水= =)
在前面继承关系的图中,我们可以看出所有插值器继承自BaseInterpolator
,其又实现了Interpolator
接口,而Interpolator
接口继承自TimeInterpolator
接口,TimeInterpolator
接口中的唯一抽象方法为getInterpolation(float input)
,这个方法是由系统调用的,其中的参数input代表动画的时间,在0和1之间,也就是开始和结束之间。
我们可以看一下系统提供的插值器,如AccelerateDecelerateInterpolator
,其源码极其极其简单,如下:
@HasNativeInterpolator
public class AccelerateDecelerateInterpolator extends BaseInterpolator
implements NativeInterpolatorFactory {
public AccelerateDecelerateInterpolator() {
}
@SuppressWarnings({"UnusedDeclaration"})
public AccelerateDecelerateInterpolator(Context context, AttributeSet attrs) {
}
public float getInterpolation(float input) {
return (float)(Math.cos((input + 1) * Math.PI) / 2.0f) + 0.5f;
}
/** @hide */
@Override
public long createNativeInterpolator() {
return NativeInterpolatorFactoryHelper.createAccelerateDecelerateInterpolator();
}
}
可以看到,核心方法就是前面提到的getInterpolation()
,其效果就是通过这一数学公式得来的,好久不看数学,已经快看不懂这个公式结果是什么了,汗颜= =
public float getInterpolation(float input) {
return (float)(Math.cos((input + 1) * Math.PI) / 2.0f) + 0.5f;
}
由此我们总结以下JAVA方式自定义插值器:
- 根据需求实现
TimeInterpolator
接口 - 实现抽象方法
getInterpolation()
,在该方法中处理逻辑 - 为动画设置该自定义插值器处。