Android动画基础总结
Android动画主要分为两种,视图动画和属性动画,视图动画又分为补间动画和帧动画两种。补间动画包含透明动画(Alpha),缩放动画(Scale),平移动画(Translate),旋转动画(Rotate);帧动画是切换图片的动画;属性动画通过改变属性令视图达到动画效果。
目录
1. 视图动画
- 补间动画
- 帧动画
2. 属性动画
- 值动画
- 对象动画
3. 总结
1. 视图动画
1.1 补间动画
补间动画包含透明动画(Alpha),缩放动画(Scale),平移动画(Translate),旋转动画(Rotate),可以在控件上通过startAnimation方法启动动画,传入一个Animation类作为参数,这个类是AlphaAnimation,ScaleAnimation,TranslateAnimation,RotateAnimation的基类,通过AnimationUtils.loadAnimation方法进行创建。下面来一一解析。
- 透明动画(Alpha)
透明动画是一个改变视图透明度的动画。下面来创建一个透明动画:
在res/anim里新建一个xml文件 anim_alpha
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="https://schemas.android.com/apk/res/android">
<alpha
android:duration="2000"
android:fromAlpha="0.1"
android:toAlpha="1" />
</set>
其中的属性duration表示动画持续时间,fromAlpha表示透明度起始值,toAlpha表示透明度的终止值。
在布局文件里放一个TextView
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="https://schemas.android.com/apk/res/android"
xmlns:app="https://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:id="@+id/textView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="hello world"
android:textColor="#000"
android:textSize="48dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</android.support.constraint.ConstraintLayout>
通过AnimationUtils.loadAnimation方法创建一个Animation,传入两个参数,第一个是页面的Context,第二个是anim文件
var animation: Animation = AnimationUtils.loadAnimation(this, R.anim.anim_alpha)
通过startAnimation方法启动动画
textView.startAnimation(animation)
运行代码,textView在2秒内从透明度为0.1渐变到1。
- 缩放动画(Scale)
缩放动画是一个改变视图大小的动画。下面来创建一个缩放动画:
在res/anim里新建一个xml文件 anim_scale
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="https://schemas.android.com/apk/res/android">
<scale
android:duration="2000"
android:fromXScale="1"
android:fromYScale="1"
android:toXScale="0.5"
android:toYScale="0.5" />
</set>
fromXScale表示宽度起始比例,fromYScale表示高度起始比例,toXScale表示宽度终止比例,toYScale表示高度终止比例。通过startAnimation方法启动动画
var animation: Animation = AnimationUtils.loadAnimation(this, R.anim.anim_scale)
textView.startAnimation(animation)
运行代码,textView的宽高在2秒内从原来的大小缩小到一半。
- 平移动画(Translate)
平移动画是一个改变视图位置的动画。下面来创建一个平移动画:
在res/anim里新建一个xml文件 anim_translate
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="https://schemas.android.com/apk/res/android">
<translate
android:duration="2000"
android:fromXDelta="50"
android:fromYDelta="50"
android:toXDelta="200"
android:toYDelta="200" />
</set>
fromXDelta表示X轴起始位置,fromYDelta表示Y轴起始位置,toXDelta表示X轴终止位置,toYDelta表示Y轴终止位置。通过startAnimation方法启动动画
var animation: Animation = AnimationUtils.loadAnimation(this, R.anim.anim_translate)
textView.startAnimation(animation)
运行代码,textView在2秒内从x=50,y=50的位置移动到x=200,y=200的位置。
- 旋转动画(Rotate)
旋转动画是一个视图根据围绕中心点旋转的动画。下面来创建一个旋转动画:
在res/anim里新建一个xml文件 anim_rotate
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="https://schemas.android.com/apk/res/android">
<rotate
android:duration="2000"
android:fromDegrees="0"
android:pivotX="50%"
android:pivotY="50%"
android:toDegrees="361" />
</set>
fromDegrees表示起始角度,toDegrees表示顺时针旋转角度(值为负数时逆时针旋转),pivotX表示中心点X轴坐标,pivotY表示中心点Y轴坐标,如上面 pivotX=“50%”,pivotY="50% 指的是控件的中心位置。通过startAnimation方法启动动画
var animation: Animation = AnimationUtils.loadAnimation(this, R.anim.anim_rotate)
textView.startAnimation(animation)
运行代码,textView围绕自己的中心顺时针旋转361°。
- 组合动画
上面举了4种动画单个启动的例子,那么如果想把他们组合在一起,该怎么用呢。举个例子:
在res/anim里新建一个xml文件 anim_group,把上面4种动画都放进去
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="https://schemas.android.com/apk/res/android"
android:duration="2000">
<translate
android:fromXDelta="50"
android:fromYDelta="50"
android:toXDelta="200"
android:toYDelta="200" />
<rotate
android:fromDegrees="0"
android:pivotX="50%"
android:pivotY="50%"
android:toDegrees="361" />
<scale
android:fromXScale="1"
android:fromYScale="1"
android:toXScale="0.5"
android:toYScale="0.5" />
<alpha
android:fromAlpha="0.1"
android:toAlpha="1" />
</set>
这样就得到一个组合动画,启动动画的方式也是一样
var animation: Animation = AnimationUtils.loadAnimation(this, R.anim.anim_group)
textView.startAnimation(animation)
运行代码,查看效果:
- 状态停留
上面举的例子都是动画播放完后视图回到原来的位置,如果视图想保持动画播放完后的状态,可以在xml文件的标签内添加属性fillAfter,true为状态停留在动画播放完后,也可以在代码中设置。如下所示:
<set xmlns:android="https://schemas.android.com/apk/res/android"
android:duration="2000"
android:fillAfter="true">
···
</set>
//或者再代码中设置
animation.fillAfter = true
运行代码,查看效果:
- 循环播放
上面举的例子都是动画播放完就自动停止了,如果想要循环播放,可以监听动画播放,如下所示:
animation.setAnimationListener(object : Animation.AnimationListener {
override fun onAnimationRepeat(animation: Animation?) {
}
override fun onAnimationEnd(animation: Animation?) {
animation?.reset()
animation?.start()
}
override fun onAnimationStart(animation: Animation?) {
}
})
Animation.AnimationListener可以监听动画的开始、结束、重播。如果想循环播放动画,可以在动画结束时调用reset()重置动画,然后调用start()播放。如果想要停止播放,可以在视图上调用clearAnimation()清楚动画,如下所示:
textView.startAnimation(animation)
textView.setOnClickListener {
textView.clearAnimation()
}
运行代码,效果如下:
- 插值器(Interpolator)
Interpolator可以控制动画变化的速率,使动画效果能够以匀速、加速、减速等多种速率变化,默认是匀速(LinearInterpolator)。当我们需要设置Interpolator时,可以在xml文件的标签内添加属性fillAfter,true为状态停留在动画播放完后,也可以在代码中设置。如下所示:
<set xmlns:android="https://schemas.android.com/apk/res/android"
android:interpolator="@android:anim/accelerate_interpolator">
...
</set>
//或者再代码中设置
animation.setInterpolator(AccelerateInterpolator())
//为了更好地观察效果,把持续时间改为4秒
animation.duration = 4000
AccelerateInterpolator是一个加速度插值器,动画播放起始速度变慢,但是速度越来越快,如下所示:
如果觉得效果不够明显,还可以给AccelerateInterpolator设置属性factor,factor是一个float类型的值,值越大起始速度越慢,但是速度越来越快,下面把factor设置成2f再来看一下效果:
animation.setInterpolator(AccelerateInterpolator(2f))
除了AccelerateInterpolator之外,还有很多不同的插值器,下面来一一列举:
插值器 | 说明 |
---|---|
LinearInterpolator | 变化速率恒定(默认) |
AccelerateInterpolator | 开始速率较慢,后面加速 |
AccelerateDecelerateInterpolator | 开始和结束速率较慢,中间加速 |
DecelerateInterpolator | 开始速率较快,后面减速 |
AnticipateInterpolator | 开始时向后飞溅,然后向前 |
AnticipateOvershootInterpolator | 开始时向后飞溅,然后向前,结束前冲过目标值,又回到目标值 |
OvershootInterpolator | 开始时向前飞溅,结束前冲过目标值,又回到目标值 |
BounceInterpolator | 结束时反弹 |
CycleInterpolator | 动画循环播放特定的次数,速率沿着正弦曲线改变 |
1.2 帧动画
帧动画是一种一帧一帧播放的动画。下面举个例子:
首先我准备了4张图
在res/drawable里新建一个根属性为animation-list的anim_frame.xml,把4张图片放进去,其中oneshot属性如果为true时,动画只播放一次,如果为false则循环播放
<?xml version="1.0" encoding="utf-8"?>
<animation-list xmlns:android="https://schemas.android.com/apk/res/android"
android:oneshot="false">
![![giftest13.gif](https://upload-images.jianshu.io/upload_images/2787721-b8bc65b2b25c5acd.gif?imageMogr2/auto-orient/strip)
](https://upload-images.jianshu.io/upload_images/2787721-0690977f6495c791.gif?imageMogr2/auto-orient/strip)
<!--每张图播放100毫秒-->
<item
android:drawable="@drawable/pic01"
android:duration="100" />
<item
android:drawable="@drawable/pic02"
android:duration="100" />
<item
android:drawable="@drawable/pic03"
android:duration="100" />
<item
android:drawable="@drawable/pic04"
android:duration="100" />
</animation-list>
在布局文件中添加一个ImageView来播放帧动画
<ImageView
android:id="@+id/imageView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent" />
播放动画
//为ImageView设置资源
imageView.setImageResource(R.drawable.anim_frame)
//AnimationDrawable是用于创建逐帧动画的对象
var animationDrawable: AnimationDrawable
animationDrawable = imageView.drawable as AnimationDrawable
imageView.setOnClickListener {
//点击imageView启动动画
animationDrawable.start()
}
运行代码,查看结果
2. 属性动画
上面说到的补间动画,只提供了几种基础动画,可扩展性不强,而且在动画播放的过程中,只改变了视图的视觉效果,并没有改变他们的属性。为了弥补补间动画的缺点,在 Android 3.0 开始提供了属性动画。属性动画是通过改变对象属性实现的动画,分为值动画(ValueAnimator)和对象动画(ObjectAnimator)两种。
2.1 值动画(ValueAnimator)
值动画是通过控制对象属性的变化,不断赋值给对象的属性实现的动画。ValueAnimator有3个比较重要的方法:
- ValueAnimator.ofInt(int values)
- ValueAnimator.ofFloat(float values)
- ValueAnimator.ofObject(int values)
以ofInt(int values)为例,介绍一下值动画实现方法:
1.创建值动画实例,调用ValueAnimator.ofInt(int values)设置值范围,当参数为一个时,传入的参数为结束值;当参数为两个时,第一个参数为起始值,第二个参数为结束值。
2.设置动画播放的各种属性
- setDuration(long duration)
设置播放时长 - setStartDelay(long duration)
设置延迟播放时间 - setRepeatCount(int value)
设置重复播放次数,value为0时不重播,value为ValueAnimator.INFINITE时无限重播 - setRepeatMode(int value)
设置重播模式,value为ValueAnimator.RESTART(默认)时正序重放,value为ValueAnimator.REVERSE时倒序回放
3.调用addUpdateListener()监听动画播放,通过估值器(ValueAnimator.ofInt()方法默认估值器为IntEvaluator),每变化一次,估值器就会根据比例、起始值、结束值来计算具体变化数值,然后把新的值赋给对象的属性,再重新绘制。
4.开始动画
完整代码如下
val anim = ValueAnimator.ofInt(textView.layoutParams.width, 500)
anim.setDuration(3000)//播放时间为3秒
anim.setStartDelay(0)//不延迟播放
anim.setRepeatCount(0);//不重播
anim.repeatMode = ValueAnimator.RESTART//正序重播
anim.addUpdateListener {
var value = it.getAnimatedValue() as Int//获取变化后的值
textView.layoutParams.width = value//新的值赋给对象的属性
textView.requestLayout()//重新绘制
}
textView.setOnClickListener { anim.start() }
点击textView动画开始,textView会在3秒内从原来的宽度拉长到目标值500,效果如下:
ofFloat()与ofInt()大同小异,ofInt()将起始值以整形数值的形式过渡到结束值,而ofFloat()将起始值以浮点型数值的形式过渡到结束值。ofFloat()的默认估值器为FloatEvaluator。ofObject()与前两个方法不同的是,它以对象的形式将起始值过度到结束值,没有默认的估值器,只能通过自定义估值器来实现。
2.2 对象动画(ObjectAnimator)
ValueAnimator通过监听动画播放,不断获取并更新对象的属性值,实现动画效果,算是一个“手动”赋值的方式,而ObjectAnimator则是一种“自动”的方式。ObjectAnimator继承ValueAnimator,所以在用法上他们差别不大,下面举个例子:
用ObjectAnimator实现像补间动画的缩放动画那样的效果,代码如下:
val animator = ObjectAnimator.ofFloat(textView, "scaleX", 1f, 2f)
animator.setDuration(3000)
animator.start()
首先创建ObjectAnimator实例,调用ofFloat()方法并传入对应的参数,第一个参数为展示动画的对象,第二个参数为需要改变的属性,这个参数可以传入任意属性名,ObjectAnimator根据该属性名找到该对象属性的get() & set()方法进行“自动”赋值,如上面传入"scaleX",ObjectAnimator会调用scaleX的get() & set()方法对其属性进行赋值,所以如果需要采用ObjectAnimator类实现动画效果,那么需要操作的对象就必须有该属性的get() & set()方法。后面的参数为起始结束值,如果属性没有提供起始值,则调用属性的get()方法取值。因为ObjectAnimator继承ValueAnimator,所以可以跟ValueAnimator一样设置动画播放的各种属性。运行代码:
textView在3秒内从自身宽度拉长到两倍。
同样的如果要自定义对象动画,只需仿照上面例子,定义好需要操作的属性,并提供该属性的get() & set()方法。关于如何自定义对象动画,本篇就不再详解了。
3. 总结
本篇文章主要介绍了Android动画分为视图动画和属性动画两种,视图动画又分为补间动画和帧动画。帧动画主要是以一帧一帧地播放图片来展示动画;补间动画主要以透明度、缩放、选择、平移等改变视图的显示方式来展示动画;属性动画分为以“手动”或“自动”改变对象的属性值的方式来展示动画。Android动画能让app与用户交互的时候变得更有趣,而实际上在开发中也是经常会运用到动画知识,所以学好Android动画也是每一个Android开发者的必修课。本篇文章内容浅显,只说到了动画的基础知识,后面会由浅入深继续介绍Android动画,有兴趣的可以继续关注。
共同学习,写下你的评论
评论加载中...
作者其他优质文章