这是我这个系列的目录,有兴趣的可以看下: android 动画系列 - 目录
tween 动画早些时候我们也叫补间动画(我也不知道为啥),现在也有叫 view 动画的。tween动画是2.X 时代的产物,因为效果不理想,4.X 时代推出了动画的升级版 属性动画。给我的感觉 属性动画就是tween动画的升级版,属性动画就是替换 tween 的,现在来看也的确时这样的,大部分的场景我们现在都是使用属性动画的,只有一些较老的 api 中会使用 tween 动画。
既然tween 动画和属性动画是承前启后的关系,那么2者理所应当的在使用是很相似,参数也很相似,这里有些参数我们在 tween 动画这节中介绍过后,就不再属性动画中介绍了。
tween 动画实现的的4种动画效果:
- 平移动画 TranslateAnimation
- 缩放动画 ScaleAnimation
- 旋转动画 RotateAnimation
- 透明度动画 AlphaAnimation
对于tween 动画,目前使用的机会并不是很多了,使用时一般都是使用 定义好的动画xml文件,推荐大伙这么做。
xml 文件定义的位置:/res/anim目录下
通用 xml 属性介绍
上面这些都是我在定义 xml tween 动画时会用到的属性,上面的表里基本上很全了,解释的也很到位
android:startOffset="100" 注意这个 startOffset 参数,这是动画执行的延迟时间,tween 动画使用 startOffset 属性,属性动画使用 delay 属性,这是 tween 和属性动画在定义时需要注意的,话说使用同一个单词不好嘛,非要用2个...
tween 动画数值体系和坐标体系
先来说一下坐标体系,这个属于大家应该熟记的,也是能猜测出来的,tween 动画时作用与 view 之上的,那么 tween 的坐标体系也是以目标 view 的坐标为参考的。具体来说就是以 目标 view 的左上角为坐标原点。明白这点我么再往下面看。
细心的朋友应该会发现,我们在设置 tween 动画参数时出现过3种不同的写法:30,30%,30%p。这3种写法有其不同的含义,我们来仔细看一下。
参数数值体系,这里以平移来举例:
- 30,以目标 view 的左上角为原点,让 view 向右移动30px
- 30%,以目标 view 左上角为原点,让 view 向右移动 view 宽度的30%
- 30%p,以目标 view 左上角为原点,让 view 向右移动父容器宽度的30%
了解了 tween 动画的坐标系,再来看动画的数值参数,移动的方向大伙都应该知道了,那么具体上面3种写法就是偏移量的不同了,30是 px 像素,30%是以 view 自身宽高算的,30%p 是以 view 的父容器的宽高算的
缩放,旋转动画的中心点大伙应该都恩那个猜出来是view 的左上角了吧,我们学习很重要的一点就是举一反三,看破一点,总揽全局。
translate位移动画
效果图:添加了自动返回的代码
tween 动画我们可以使用 xml 来定义,也可以自己撸代码
xml 定义:
<?xml version="1.0" encoding="utf-8"?>
<translate xmlns:android="http://schemas.android.com/apk/res/android"
android:duration="600"
android:fromXDelta="0"
android:fromYDelta="0"
android:repeatCount="1"
android:repeatMode="reverse"
android:toXDelta="100"
android:toYDelta="100"
/>
我们定义完 xml 文件后,不就是完事了,我们还得把动画绑定给一个 view ,并开始才能启动动画效果
Animation animation1 = AnimationUtils.loadAnimation(this, R.anim.tran1); // R.anim.tran1是我们定义号的动画 xml
imageTest.startAnimation(animation1); // imageTest是要显示动画的 view
这样我们就可以使用tween 动画了,当然这是最简单的使用方式了,注意看所有的 tween 动画的都实现了 Animation接口。
对于 xml 的定义,虽然上面介绍过参数的含义了,我在这里还是说一下的好,便于理解啊。
- duration 是动画执行时间,我们要是不写的话,默认是300ms,在 xml 中,时间都是以 ms 为单位的
- fromXDelta/fromYDelta 是动画开始时 view x/y 轴的偏移量,一般我们都写0,
- toXDelta/toYDelta 是位移动画在 view x/y 轴上最终的偏移量,也可以理解为我们想让 view 到达的新位置,也可以理解为动画的执行幅度
- repeatMode 是动画的重复模式,有2个模式:reverse/restart。 reverse是回复原状,restart是重复执行。
- repeatCount 是动画的重复次数
- Animator.setRepeatCount(ValueAnimator.INFINITE) 也可以实现重复执行的效果
- fillAfter 动画执行后是否保留 view 所在的新位置, true 保留,false 回归初始位置
- fillBefore 和fillAfter不一样,不论是 true 还是 false,都会回归初始位置
这里注意 repeatMode/repeatCount ,这2个参数必须都写才有意思,只写一个是不成立的,我在下面会专门说下重复模式和重复次数的问题,这个和大家想象有些不一样,我可是专门都跑了一遍才清楚的。
java 代码定义:
TranslateAnimation translateAnimation = new TranslateAnimation(0, 100, 0, 100);
translateAnimation.setDuration(600);
translateAnimation.setRepeatMode(TranslateAnimation.REVERSE);
translateAnimation.setRepeatCount(1);
imageTest.startAnimation(translateAnimation);
我们也是可以 new 一个 tween 动画的直接实现类出来的,这里使用的是 TranslateAnimation 最简单的构造函数
上面说了 tween 动画有3种参数形式:30,30%,30%p,这里我们就来试试看啊,不试试怎么能清楚尼...
让我们来看看30%,上面使用的是100px,现在我们来看看100%是啥样子的,看看和猜测的是不是一样,向右位移自身尺寸的100%后,应该是靠近右侧边缘了
<?xml version="1.0" encoding="utf-8"?>
<translate xmlns:android="http://schemas.android.com/apk/res/android"
android:duration="600"
android:fillAfter="true"
android:fromXDelta="0"
android:fromYDelta="0"
android:toXDelta="100%"
android:toYDelta="100%"
/>
效果图:
啊,和我们预计的一样,向右位移了 view 自身的宽高值,和明显的能够看出来
接下来让我们看看 30%p,为了效果明显,数值这里使用了 80%p
<?xml version="1.0" encoding="utf-8"?>
<translate xmlns:android="http://schemas.android.com/apk/res/android"
android:duration="600"
android:fillAfter="true"
android:fromXDelta="0"
android:fromYDelta="0"
android:toXDelta="80%p"
android:toYDelta="80%p"
/>
效果图:
哈哈,大伙注意啊,这里 view 的父控件可是根视图节点了,所以向右偏移量很大,直接出去了,大伙没有没想过要是给这个 view 添加一个父控件,会怎么样呢...让我们来看看:
view 的大小是100dp,给view 添加一个200dp 的外壳,蓝色背景
xml布局:
<RelativeLayout
android:layout_width="200dp"
android:layout_height="200dp"
android:layout_centerHorizontal="true"
android:background="@color/colorPrimary">
<ImageView
android:id="@+id/acg"
android:layout_width="100dp"
android:layout_height="100dp"
android:layout_centerInParent="true"
android:layout_marginTop="50dp"
android:src="@color/colorAccent"/>
</RelativeLayout>
动画不变,还是设置80%p
效果图:
啊嘞,咱们的粉色的 view 怎么没了,啦啦啦,大伙不知道平时注意没有,viewGroup 是不允许子控件超出自己的范围的,所以咱们的 view 在位移出父控件的范围后就消失不见了,这里我们需要设置一下:
需要在布局根节点设置android:clipChildren="false"才行,注意不是在这个父控件设置,是在 xml 的根节点设置,这点要注意啊,看我的这篇文章 Android 布局小技巧汇总
xml 根节点设置 android:clipChildren="false" 才行
效果图:
这样接可以看到效果了,这次位移的幅度就是我们添加的这个200dp 的父控件了
scale 缩放动画
效果图:
这是缩放的效果,和预想的有点不同的是,缩放中心点怎么不是 view 的中心呢,那么我们来看下 xml 代码:
<?xml version="1.0" encoding="utf-8"?>
<scale xmlns:android="http://schemas.android.com/apk/res/android"
android:duration="600"
android:fillAfter="true"
android:fromXScale="1"
android:fromYScale="1"
android:toXScale="0.3"
android:toYScale="0.3"
/>
恩,看上面的 xml 设置中,里面没有设置缩放中心点的参数,那么上面的缩放就是走的是默认设置了,可以看到:缩放的默认中心点是 view 的左上角,这也是 tween 动画坐标系的原点,从这一点考虑也是可以理解默认中心点在左上角的设置了。
上面 xml 中属性的设置很好理解,fromXX是动画开始的数值,toXX 是动画结束时的数值,这里说一下,缩放的数值 1 是原始大小,0是没有大小,2是原始大小的2倍,所以说缩放的参数很好理解。
上面没写缩放中心点设置,那么当然中心点也是可以设置的,参数是:pivotX/pivotY,中心点的坐标,比如中心点设置在 view 的中心,数值可以这样写:50% 。写0.5表示偏移量是px 值。50%p表示中心点在view 的左上角坐标+父容器的宽高的一半之后的位置
xml
<?xml version="1.0" encoding="utf-8"?>
<scale xmlns:android="http://schemas.android.com/apk/res/android"
android:duration="600"
android:fillAfter="true"
android:fromXScale="1"
android:fromYScale="1"
android:pivotX="50%"
android:pivotY="50%"
android:toXScale="0.3"
android:toYScale="0.3"
/>
效果图:
rotate 旋转动画
效果图:
xml:
<?xml version="1.0" encoding="utf-8"?>
<rotate xmlns:android="http://schemas.android.com/apk/res/android"
android:duration="600"
android:fillAfter="true"
android:fromDegrees="0"
android:pivotX="50%"
android:pivotY="50%"
android:toDegrees="360"
/>
rotate 和 scale 差不多,除了数值不同,其他都一样。rotate 因为是旋转,所以参数肯定是设置的旋转多少度,需要注意的是正数是顺时针转,负数是逆时针转,其他的没什么可说的了。
alphe 透明度动画
效果图:
xml:
<?xml version="1.0" encoding="utf-8"?>
<alpha xmlns:android="http://schemas.android.com/apk/res/android"
android:duration="600"
android:fillAfter="true"
android:fromAlpha="1"
android:toAlpha="0"
/>
哈哈,看完上面的 alphe透明度动画很简单了吧,注意数值1是不透明,0是完全透明。
tween动画的 repeat 重复模式
translate 的第一个效果图就是使用了动画的重复模式的,简单的说重复模式就是在动画结束后对 view 进行一些逻辑上的操作,可以重复执行和反向执行。
这里设计到2个参数设置: repeatMode / repeatCount,重复模式 / 重复次数
先看一下xml 的属性设置
<?xml version="1.0" encoding="utf-8"?>
<translate xmlns:android="http://schemas.android.com/apk/res/android"
android:duration="600"
android:fillAfter="true"
android:fromXDelta="0"
android:fromYDelta="0"
android:repeatCount="1"
android:repeatMode="reverse"
android:toXDelta="80%"
android:toYDelta="80%"
/>
这里一个位移动画,里面设置有重复模式和重复次数。首先说明一下,repeatMode和repeatCount二者缺一不可,必须都得写才能生效
repeatMode 分2种:
- reverse 反向执行动画,就是动画时怎么来的,就怎么回去
- restart 重复执行动画,就是动画反复执行,不过注意动画结束后就会回到初始位置,显得有些突兀
我们来看看效果是什么样的,这样才好理解不是,注意这里 repeatCount 都是设置为1
reverse 反向执行效果图:
restart 重复执行效果图:
这里使用了高采样率转换的 gif,可以很 清楚的看出来在第一次动画执行完后瞬间 view 就回归到了初始位置再执行了一次动画,中间切换的效果太突兀了,不是很友好。
好了看完了 repeatMode ,那么大家来猜测下 repeatCount 重复次数的使用规律,其实看完上面的都应该明白了,重复次数是指动画在执行完成后再按照某种方式执行多少次,我们写在 repeatCount 里面的数字是不包含第一次的,注意这点基本就可以了,比如我们想让上面这个动画来回执行2个大循环,既动画执行完后反向执行一次这算一个大循环,那么repeatCount我们写几呢,是3,不算第一次,大伙算算,自己试试,下面是效果图:
好了是不是很咱们想的一样,自己多动手,多试试,google 的 api 基本我们都能搞明白。
AnimationSet 动画集合
android 中的动画不单单可以单独执行一种效果,更是可以多个动画效果一起执行的。下面看个例子:
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
android:duration="600"
android:interpolator="@android:anim/accelerate_decelerate_interpolator"
android:shareInterpolator="true">
<translate
android:fromXDelta="0"
android:fromYDelta="0"
android:repeatCount="1"
android:repeatMode="reverse"
android:toXDelta="80%"
android:toYDelta="80%"/>
<alpha
android:fromAlpha="1"
android:repeatCount="1"
android:repeatMode="reverse"
android:toAlpha="0.2"/>
</set>
效果图:
单个动画中有的参数可以写到 set 动画集合中去,比如时间,但是重复这块就不行了,我需要写到单个里才行
set 中有2个新的属性 interpolator 这个是插值器,是控制动画执行曲线的,系统提供的默认值就够我们使用的了,shareInterpolator 是设置所有的单项动画是否都使用 set 中的这个插值器,具体的插值器我们下节说,一看就懂
监听方法
差点忘了动画是可以加监听的,很多时候我们在动画执行完成后要做点什么不是嘛
animation1.setAnimationListener(new Animation.AnimationListener() {
@Override
public void onAnimationStart(Animation animation) {
}
@Override
public void onAnimationEnd(Animation animation) {
}
@Override
public void onAnimationRepeat(Animation animation) {
}
});
AniamtionSet 动画集合也是可以添加监听的。上面的代码中提供了3个回调函数,中规中矩,开始,结束,重复。
总结
好了最后让我们来总结下使用时的注意点:
- 4种动画,位移支持3种参数形式,其他的不行
- 重复模式和重复次数要搞清楚
tween 动画虽然现在用的机会很少了,但是这是 android 动画的基础,之后的属性动画在使用时参数也是大体没有变化的。所以学好 tween 动画,有其是期中一些参数的数值范围,效果是很有必要的。好了就这么多了,更多的在参考资料里啦