有5种:
alpha 渐变透明度动画效果
scale 渐变尺寸伸缩动画效果
translate 画面转换位置移动动画效果
rotate 画面转移旋转动画效果
layoutAnimation 容器中的控件应用统一动画
首先,创建一个 目录 具体 步骤如下:
选:anim 目录
OK,看目录,创建一个 动画文件:set
命名为: my_animat
好了 ,我们在这个set 添加我们所需要的动画。
可以既是一个动画,也可以是多个动画的组合
现在暂且先一个一个来,演示平移动画:
看下动画目标View 的设置,用了一个TextView 注意:用了 宽高 是300px 像素,,,像素,,,像素
为什么用 px呢,会说到的
然后动画 translate_ani.xml 注意:fillAfter="true" View 最后会停留在动画结束的地方
看下原始的截图
看下Activity 中的layout: activity_animator.xml
Activity的代码:
package com.leo.dicaprio.myutilapp.animator
import android.content.Context
import android.os.Bundle
import android.support.v7.app.AppCompatActivity
import android.view.animation.AnimationUtils
import android.widget.Toast
import com.leo.dicaprio.myutilapp.R
import kotlinx.android.synthetic.main.activity_animator.*
import org.jetbrains.anko.startActivity
class AnimatorActivity : AppCompatActivity() {
companion object {
fun launch(context: Context) {
context.startActivity()
}
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_animator)
tv_animator.setOnClickListener { Toast.makeText(this, "被单击了", Toast.LENGTH_LONG).show() }
tv_animator1.setOnClickListener { startAni1() }
tv_animator2.setOnClickListener { startAni2() }
tv_animator3.setOnClickListener { startAni3() }
tv_animator4.setOnClickListener { startAni4() }
}
/**
* 平移动画
* */
private fun startAni1() {
//先加载 平移动画
val animation = AnimationUtils.loadAnimation(this, R.anim.translate_ani)
tv_animator.startAnimation(animation)
}
}
点击一下,动画过度效果就不生产 gif了,直接上最后结果
可以看到最后的结果。这时候 手机开了开发者模式的边界布局的。
分析下:
目标的 View 宽高是 300*300 像素,现在 动画 的 toXDelta和toYDelta都是300,表示向X Y 轴正方向移动 300像素。
为什么这么肯定 toXDelta 的单位是 像素呢? 从 截图看,可以理解为:目标 View 基于源点(左上角坐标)在XY方向 移动的距离,刚好是目标的宽高。。。
by the way ! 这个时候你点蓝色区域,是不会弹Taost,只有点击原始的位置,才会弹Toast。所以View动画并没有改变
View的属性。所以目标动画View是有点击事件的话,用View动画实现不了功能的。。。这个注意下。
好了,基本上可以理解完了。其实 translate 标签,是对应 TranslateAnimation()
可以用它,代码改成:
/**
* 平移动画
* */
private fun startAni1() {
//先加载 平移动画
// val animation = AnimationUtils.loadAnimation(this, R.anim.translate_ani)
// tv_animator.startAnimation(animation)
//单位是像素
val translateAnimation = TranslateAnimation(0F, 300F,0F , 300F)
translateAnimation.fillAfter = true//停留在结束地方
translateAnimation.duration = 500//时间
tv_animator.startAnimation(translateAnimation)
}
同样的效果!!!
另外,通过这个TranslateAnimation 还可以监听 动画的执行状态,比如:开始,结束,重复......
比如:
/**
* 平移动画
* */
private fun startAni1() {
//先加载 平移动画
// val animation = AnimationUtils.loadAnimation(this, R.anim.translate_ani)
// tv_animator.startAnimation(animation)
val translateAnimation = TranslateAnimation(0F, 300F, 0F, 300F)
translateAnimation.setAnimationListener(object : Animation.AnimationListener {
override fun onAnimationRepeat(animation: Animation?) {
//动画重复
}
override fun onAnimationEnd(animation: Animation?) {
//动画结束
}
override fun onAnimationStart(animation: Animation?) {
//动画开始
}
})
translateAnimation.fillAfter = false//停留在结束地方
translateAnimation.duration = 500//时间
tv_animator.startAnimation(translateAnimation)
}
透明比较简单。。。。上alpha_ani.xml 代码:
Activity 引用
/**
* 透明动画
* */
private fun startAni2() {
//先加载 透明动画
val animation = AnimationUtils.loadAnimation(this, R.anim.alpha_ani)
tv_animator.startAnimation(animation)
/*
* 或者
* */
val alphaAnimation = AlphaAnimation(1.0F, 0F)
alphaAnimation.fillAfter = true
alphaAnimation.duration = 5000
tv_animator.startAnimation(alphaAnimation)
}
旋转,一般四个参数
fromDegrees 开始时的角度
toDegrees 结束时角度 ,正代表顺时针
pivotX 旋转中心轴点 X坐标 不指定 默认是View 左上角 X坐标 单位像素
pivotY 旋转中心轴点 Y坐标 不指定 默认是View 左上角 Y坐标 单位像素
不说废话,上 目标View,哈哈,同样是一个TextView,同样是 300*300 px
上动画文件:anim /rotate_ani.xml
注意!!! pivotX 和 pivotY 是150,刚好是TextView宽高的一半。
Activity调用:
/**
* 旋转动画
* */
private fun startAni3() {
//先加载 旋转动画
val animation = AnimationUtils.loadAnimation(this, R.anim.rotate_ani)
tv_animator.startAnimation(animation)
/*
* 或者
* */
val rotateAnimation = RotateAnimation(0F, 180F, 150F, 150F)
rotateAnimation.fillAfter = true
rotateAnimation.duration = 5000
tv_animator.startAnimation(rotateAnimation)
}
测试的结果,是在TextView是 300*300 px时,
1> pivotX和pivotY都为150,旋转中心为 TextView的中心
1> pivotX和pivotY都为0, 旋转中心为 TextView的左上角
所以,结论是:这个旋转圆点坐标,是基于目标View左上角(0,0)坐标的。
缩放。。。。。。
fromXScale,fromYScale X Y 方向 缩放起始值
toXScale, toYScale X Y 方向 缩放结束值
pivotX ,pivotY X Y 方向 缩放中心值 中心点也是和上面的基准规则一样
代码都不贴了,都一样的·原理。。。。。
多个动画同时播放:
my_toget__animat.xml代码: 多个动画(透明,旋转,缩放)一起
view层的处理:运行结果是 (透明,旋转,缩放)同事进行
private fun animationSet(){
//加载
val animation = AnimationUtils.loadAnimation(this, R.anim.my_toget__animat)
tv_animator_view.startAnimation(animation)
}
这个可以不用 xml类型,可以用代码动态,比如:
private fun animationSet(){
val rotateAnimation = RotateAnimation(0F, 180F, 150F, 150F)
val alphaAnimation = AlphaAnimation(1.0F, 0F)
val scaleAnimation = ScaleAnimation(0F, 1F, 0F, 1F, 150F, 150F)
//多个动画 放进 AnimationSet
val animationSet = AnimationSet(true)
animationSet.addAnimation(rotateAnimation)
animationSet.addAnimation(alphaAnimation)
animationSet.addAnimation(scaleAnimation)
animationSet.duration = 5000
tv_animator_view.startAnimation(animationSet)
}
动态代码设置 AnimationSet 集合,把需要的动画放进去,效果是一样的
多个动画按顺序播放:
顺序播放的思路,在xml是用延时法 通过 startOffset 指定延迟执行动画
比如:
加载设置用法是一样的,就不贴了
使用代码设置 顺序,监听第一个动画完成,再进行第2个动画
private fun animationOrder(){
val rotateAnimation = RotateAnimation(0F, 180F, 150F, 150F)
rotateAnimation.fillAfter = true
rotateAnimation.duration = 5000
rotateAnimation.setAnimationListener(object :Animation.AnimationListener{
override fun onAnimationRepeat(animation: Animation?) {
//动画重复
}
override fun onAnimationEnd(animation: Animation?) {
//动画结束
val alphaAnimation = AlphaAnimation(1.0F, 0F)
alphaAnimation.fillAfter = true
alphaAnimation.duration = 5000
tv_animator_view.startAnimation(alphaAnimation)
}
override fun onAnimationStart(animation: Animation?) {
//动画开始
}
})
tv_animator_view.startAnimation(rotateAnimation)
}
作用于 ViewGroup,为一个ViewGroup指定一个动画,他的所有子元素,出厂时都会具有这个动画效果
比如在RecycleView指定时,每个item都会有
比如在ViewGroup指定时,每个子View都会有
首先,创建 layoutAnimation : anim/layout_animation.xml
创建 layoutAnimation : anim/ alpha.xml
父布局 layout文件:
注意!! 父布局的 visibility = invisible的,当父布局变成:visible后,三个子view 就会显示出来
当然,出现的形式是以动画的形式的。。。
在代码里调用:
private fun layoutAnimation() {
tv_animator_contain.visibility = View.VISIBLE
}
直接把父布局显示出来即可,所有子View的出现,都会有动画效果。。。。
你也可以在父布局 layout不设置,通过 LayoutAnimationController
直接上代码:
private fun layoutAnimation() {
val loadAnimation = AnimationUtils.loadAnimation(this, R.anim.alpha_ani)
val animationController = LayoutAnimationController(loadAnimation)
animationController.delay = 0.1F
animationController.order = LayoutAnimationController.ORDER_NORMAL
tv_animator_contain.layoutAnimation = animationController
tv_animator_contain.visibility = View.VISIBLE
}
代码引用的是 alpha_ani.xml,直接引用动画文件,并不是引用 layoutAnimation
首先说下,帧动画,是类似于视频播放那样,一秒显示26张图片,肉眼看到的效果就是视频了。
帧动画,会一下子把所有图片加载内存,然后每隔设定duration,就展示下一张图片。。。
首先,创建帧动画,是在 drawable目录下的 。。。
然后选择 animation-list
然后
在控件里使用:
/**
* 帧动画
* */
private fun startFrameAni() {
//先设置
tv_animator_view.setBackgroundResource(R.drawable.frame_animation)
//再获取 强转成 AnimationDrawable
val background = tv_animator_view.background as AnimationDrawable
//开启动画
background.start()
}
再说一次,这个如果 图片过多的话,容易导致OOM
如果非得 使用帧动画,可以 把 需要的 drawable的ID全部放进一个List里面
然后自己写一个定时器(比如用Handler),隔多少秒,通过ID获取drawable 展示一个图片,这样避免一下子把所有图片加载到内存。。。。
好了。。。。。。这边就到这里
下篇写:属性动画
上面代码亲测没问题,,,,有问题请留言指正,,,谢谢!!!!