android 动画系列 (1) - tween 动画(view动画)

这是我这个系列的目录,有兴趣的可以看下: 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 属性介绍

Snip20170722_18.png

上面这些都是我在定义 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位移动画

效果图:添加了自动返回的代码

ezgif.com-video-to-gif.gif

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%"
/>

效果图:

ezgif.com-video-to-gif.gif

啊,和我们预计的一样,向右位移了 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"
/>

效果图:

ezgif.com-video-to-gif.gif

哈哈,大伙注意啊,这里 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

效果图:

ezgif.com-video-to-gif.gif

啊嘞,咱们的粉色的 view 怎么没了,啦啦啦,大伙不知道平时注意没有,viewGroup 是不允许子控件超出自己的范围的,所以咱们的 view 在位移出父控件的范围后就消失不见了,这里我们需要设置一下:

需要在布局根节点设置android:clipChildren="false"才行,注意不是在这个父控件设置,是在 xml 的根节点设置,这点要注意啊,看我的这篇文章 Android 布局小技巧汇总

xml 根节点设置 android:clipChildren="false" 才行


Snip20170724_20.png

效果图:

ezgif.com-video-to-gif.gif

这样接可以看到效果了,这次位移的幅度就是我们添加的这个200dp 的父控件了


scale 缩放动画

效果图:


ezgif.com-video-to-gif.gif

这是缩放的效果,和预想的有点不同的是,缩放中心点怎么不是 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"
/>

效果图:

ezgif.com-video-to-gif.gif

rotate 旋转动画

效果图:

ezgif.com-video-to-gif.gif

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 透明度动画

效果图:

ezgif.com-video-to-gif.gif

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 反向执行效果图:


ezgif.com-video-to-gif.gif

restart 重复执行效果图:


ezgif.com-video-to-gif.gif

这里使用了高采样率转换的 gif,可以很 清楚的看出来在第一次动画执行完后瞬间 view 就回归到了初始位置再执行了一次动画,中间切换的效果太突兀了,不是很友好。

好了看完了 repeatMode ,那么大家来猜测下 repeatCount 重复次数的使用规律,其实看完上面的都应该明白了,重复次数是指动画在执行完成后再按照某种方式执行多少次,我们写在 repeatCount 里面的数字是不包含第一次的,注意这点基本就可以了,比如我们想让上面这个动画来回执行2个大循环,既动画执行完后反向执行一次这算一个大循环,那么repeatCount我们写几呢,是3,不算第一次,大伙算算,自己试试,下面是效果图:

ezgif.com-video-to-gif.gif

好了是不是很咱们想的一样,自己多动手,多试试,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>

效果图:

ezgif.com-video-to-gif.gif

单个动画中有的参数可以写到 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 动画,有其是期中一些参数的数值范围,效果是很有必要的。好了就这么多了,更多的在参考资料里啦


参考资料

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 195,898评论 5 462
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 82,401评论 2 373
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 143,058评论 0 325
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,539评论 1 267
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,382评论 5 358
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,319评论 1 273
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,706评论 3 386
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,370评论 0 254
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,664评论 1 294
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,715评论 2 312
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,476评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,326评论 3 313
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,730评论 3 299
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,003评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,275评论 1 251
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,683评论 2 342
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,877评论 2 335

推荐阅读更多精彩内容

  • 1 背景 不能只分析源码呀,分析的同时也要整理归纳基础知识,刚好有人微博私信让全面说说Android的动画,所以今...
    未聞椛洺阅读 2,662评论 0 10
  • Android 自定义View的各种姿势1 Activity的显示之ViewRootImpl详解 Activity...
    passiontim阅读 171,127评论 25 707
  • 2017.4.19-2017.4.28 第二篇总结 十天一晃乎过去了,没有多所得。辞了职,换到另一个城市,认识另外...
    周溜遛阅读 184评论 2 0
  • 描述情景:利用代理委托和事件我们处理 老板 员工 包含的动作 买烟 涨工资实现:老板要抽烟需要买烟会让员工去买烟,...
    lotawei阅读 981评论 0 1
  • 在经历了昨天撕心裂肺的挣扎以后 今天也假装看开了一小下 如果我是个有耐心的人 此时我写的应该是阿甘正传的观后感 而...
    选梦_e419阅读 250评论 0 0