自定义View(一)-动画- XML生成View动画

前言

感觉好久没有写博客了。首先因为最近比较忙,有在学习即时通讯相关的开源项目,好不容易忙完了。有点时间就抓紧写博客。之前学习的开源项目百篮应用已经获得360+star了。当初学习的时候没有觉得什么。虽然不是我自己原创的项目。但是也是自己一点点写出来的,也学习到了很多。所以当初的2个承诺,一个是完善功能另一个写一个学习自定义View系列文章。个人觉得第二个比较重要。因为在理解后如何去完善,是仁者见仁智者见智的事情。 这里需要注意:本人只是一个Android的小白,所以对于自定义View这个部分相比之下还是比较难的,所以文本是自己学习的总结。所以部分内容会借鉴于很多优秀的文章,如果不妥。请私信联系我,我会第一时间处理。


动画介绍

在Android动画中,总共有两种类型的动画View Animation(视图动画)和Property Animator(属性动画) 区别: 1. 引入时间不同: View Animation是API Level 1就引入的。Property Animation是API Level 11引入的,即Android 3.0才开始有Property Animation相关的API。 2. 所在包名不同: View Animation在包android.view.animation中。而Property Animation API在包 android.animation中。 3. 动画类的命名不同: View Animation中动画类取名都叫XXXXAnimation,而在Property Animator中动画类的取名则叫XXXXAnimator

那么两者的使用场景和具体的区别呢?这里先留个疑问。等我们分析到属性动画的时候再去揭晓!

使用

首选,我们学习一些视图动画:

动画

释义

alpha

渐变透明度动画效果

scale

渐变尺寸伸缩动画效果

translate

画面转换位置移动动画效果

rotate

画面转移旋转动画效果

这是动画相关变换的形式,相信大家也并不陌生!他们的属性可以简单分成两类:一个是继承而来的;另一个自己独有的。 继承而来: Animation类是所有动画(scale、alpha、translate、rotate)的基类。所这这四种动画都有一些共有的属性。如下 android:duration   动画持续时间,以毫秒为单位 android:fillAfter   如果设置为true,控件动画结束时,将保持动画最后时的状态 android:fillBefore   如果设置为true,控件动画结束时,还原到开始动画前的状态 android:fillEnabled 与android:fillBefore 效果相同,都是在动画结束时,将控件还原到初始化状态 android:repeatCount   重复次数 android:repeatMode   重复类型,有reverse和restart两个值,reverse表示倒序回放,restart表示重新放一遍,必须与repeatCount一起使用才能看到效果。因为这里的意义是重复的类型,即回放时的动作。 <font color=#006400>android:interpolator </font>   设定插值器,其实就是指定的动作效果,比如弹跳效果等。具体的插值器类型后面再详细介绍 各个动画独有属性:

alpha-透明度动画

android:fromAlpha 动画开始的透明度,从0.0 --1.0 ,0.0表示全透明,1.0表示完全不透明 android:toAlpha 动画结束时的透明度,也是从0.0 --1.0 ,0.0表示全透明,1.0表示完全不透明 在了解了共有属性和独有属性后我们具体用代码来实践一下,看下具体的效果:

alpha.gif

代码:

<?xml version="1.0" encoding="utf-8"?>
<alpha xmlns:android="http://schemas.android.com/apk/res/android"
       android:repeatCount="2"
       android:repeatMode="reverse"
       android:duration="3000"
       android:fillAfter="true"
       android:fromAlpha="1.0"
       android:toAlpha="0.5">
</alpha>

这个动画我们首先来分析下:这个动画是从全透明(1.0)到半透明(0.5),动画时长3s,结束时保持动画最后的状态,倒叙回放。重复次数是两次(重复次数不算第一次) 代码:

btn_alpha.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                mAnimation = AnimationUtils.loadAnimation(getApplicationContext(), R.anim.alpha_anim);
                mTextView.startAnimation(mAnimation);
            }
        });
alpha-尺寸变化

从名字上我们就可以看出这个动画主要是控制View的大小伸缩变换的。那么我们也是来看下它特有的属性: android:fromXScale 起始的X方向上相对自身的缩放比例,浮点值,比如1.0代表自身无变化,0.5代表起始时缩小一倍,2.0代表放大一倍; android:toXScale  结尾的X方向上相对自身的缩放比例,浮点值; android:fromYScale 起始的Y方向上相对自身的缩放比例,浮点值。 android:toYScale 结尾的Y方向上相对自身的缩放比例,浮点值; <font color=#006400>android:pivotX </font>  缩放起点X轴坐标,可以是数值、百分数、百分数p 三种样式,比如 50、50%、50%p,当为数值时,表示在当前View的左上角,即原点处加上50px,做为起始缩放点;如果是50%,表示在当前控件的左上角加上自己宽度的50%做为起始点;如果是50%p,那么就是表示在当前的左上角加上父控件宽度的50%做为起始点x轴坐标。 android:pivotY  缩放起点Y轴坐标,取值及意义跟android:pivotX一样。 这里面其他的属性还是比较好理解的主要是最后2个属性容易模糊。那么我们就针对后两个属性来着重看下:

<?xml version="1.0" encoding="utf-8"?>
<scale xmlns:android="http://schemas.android.com/apk/res/android"
       android:duration="3000"
       android:fillBefore="true"
       android:fromXScale="0.0"
       android:fromYScale="0.0"
       android:pivotX="50"
       android:pivotY="50"
       android:repeatCount="1"
       android:repeatMode="restart"
       android:toXScale="1.5"
       android:toYScale="1.5">
</scale>

这段代码的效果从属性上来看就是x,y轴都是从基于原图像0.0倍缩放到1.5倍然后回到初始状态(也就是1.0倍)然后起始点的坐标为(50,50),这里需要注意的是,在此处我们的原点坐标都是基于控件View的左上角而不是基于手机屏幕显示View左上角。 那么下面看下android:toXScale="0.5" android:toYScale="0.5" 的效果:

sacle.gif

android:toXScale="50%" android:toYScale="50%"

SCALE.gif

android:toXScale="50%p" android:toYScale="50%p"

sacl.gif

这里只改变了开始动画的坐标点参数,为了方便更好的理解我们从下面这幅图入手(这里只是方便理解点的位置不一定100%与实际一致。这里就不纠结这个问题了)

scale.gif

这里的A点是原点(0.0)当我们设置起始点为50,50时,这里可以理解为指的是具体的距离为50。那么起始点就为B点(50,50) 当我们设置起始点的坐标为50%,50%时,是指X,Y轴的距离是当前控件基于A点的50%,也就是D点控件的中心点。 最难理解的50%p,50%p,它的意思是距离是基于父布局(也就是应用显示的屏幕)计算他的距离然后算完后赋值给控件。那么屏幕的重点是C,那么它离X,Y轴的距离为X,Y,那么此时的开始点就是A(0,0)点加上X,Y就是F(X,Y)点,此时F点为动画起始点。 如果还不理解可以将动画时长改成30s或者更长,来观察下加深理解。

translate-位置变化

这个就太好理解了。就是将控件在原来的位置向指定方向或是指点移动。 <font color=#006400>android:fromXDelta </font> 起始点X轴坐标,可以是数值、百分数、百分数p 三种样式,比如 50、50%、50%p,具体意义与上面一样。 android:fromYDelta 起始点Y轴从标,可以是数值、百分数、百分数p 三种样式; android:toXDelta 结束点X轴坐标 android:toYDelta 结束点Y轴坐标

<?xml version="1.0" encoding="utf-8"?>
<translate xmlns:android="http://schemas.android.com/apk/res/android"
           android:duration="100"
           android:fillEnabled="true"
           android:fromXDelta="0"
           android:fromYDelta="0"
           android:repeatCount="1"
           android:repeatMode="reverse"
           android:toXDelta="-100"
           android:toYDelta="-100">

</translate>

注意: 在Android中,我们计算坐标相关位置的时候都是:向左为负 向上为负。 这里都没有什么难点就不在说了。看下效果图:

translatel.gif

rotate-旋转变化

android:fromDegrees 开始旋转的角度位置,正值代表顺时针方向度数,负值代码逆时针方向度数 <font color=#006400>android:toDegrees</font> 结束时旋转到的角度位置,正值代表顺时针方向度数,负值代码逆时针方向度数 android:pivotX 缩放起点X轴坐标,可以是数值、百分数、百分数p 三种样式,比如 50、50%、50%p android:pivotY 缩放起点Y轴坐标,可以是数值、百分数、百分数p 三种样式,比如 50、50%、50%p

<?xml version="1.0" encoding="utf-8"?>
<rotate xmlns:android="http://schemas.android.com/apk/res/android"
        android:duration="2000"
        android:fillAfter="true"
        android:fromDegrees="0"
        android:pivotX="50%"
        android:pivotY="50%"
        android:toDegrees="-650">
</rotate>

效果如下:

rotate.gif

set-组合动画

这个前面没有提到,这也是一个动画属性,不过他没特殊独有属性,只有继承基类Animation的共有属性,他的特点就是可以将多个动画组合在一起。如下:

<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
     android:duration="3000"
     android:fillAfter="true">

    <alpha
        android:fromAlpha="0.0"
        android:toAlpha="1.0"/>

    <scale
        android:fromXScale="0.0"
        android:toXScale="1.4"
        android:fromYScale="0.0"
        android:toYScale="1.4"
        android:pivotX="50%"
        android:pivotY="50%"/>

    <rotate
        android:fromDegrees="0"
        android:toDegrees="720"
        android:pivotX="50%"
        android:pivotY="50%"/>

</set>

效果如下:

set.gif

注意: 通常我们会把共有属性,比如:duration,repeatCount,repeatMode提取出来,如上面,当然你在每个属性中也可以单独使用,不过会很乱。而且不好控制。


Interpolator插值器

它是控制动画如何运动的一个属性。他是一个接口。那么我们来看下他的实现类有哪些

图片.png

AccelerateDecelerateInterpolator   在动画开始与介绍的地方速率改变比较慢,在中间的时候加速 AccelerateInterpolator       在动画开始的地方速率改变比较慢,然后开始加速 AnticipateInterpolator        开始的时候向后然后向前甩 AnticipateOvershootInterpolator  开始的时候向后然后向前甩一定值后返回最后的值 BounceInterpolatort        动画结束的时候弹起 CycleInterpolator        动画循环播放特定的次数,速率改变沿着正弦曲线 DecelerateInterpolator       在动画开始的地方快然后慢 LinearInterpolator          以常量速率改变 OvershootInterpolator        向前甩一定值后再回到原来位置 但是我看文档的时候发现还有一个插值器 PathInterpolator 围绕一个指定的路径做动画。 关于这个插值器先不讲解,因为他是在代码中使用,并且涉及到Path,所以我们这里先跳过。后期讲到的时候会再提一下。 这里我们简单在XML中设置BounceInterpolator(结束时弹起)插值器:

<?xml version="1.0" encoding="utf-8"?>
<rotate xmlns:android="http://schemas.android.com/apk/res/android"
        android:interpolator="@android:anim/bounce_interpolator"
        android:duration="2000"
        android:fillAfter="true"
        android:fromDegrees="0"
        android:pivotX="50%"
        android:pivotY="50%"
        android:toDegrees="-650">
</rotate>

效果:

interpolator.gif

发现效果不是很明显(是由于FPS太低的原因,真机上比较明显) 其他效果我就不一一介绍了,大家可以自己尝试下。我这里就发一个我在学习时候完成的所有插值器的效果:

GIF.gif

这里都有名字大家可以自己对照(这里我换了一个录制软件,看起来好些),不过还是自己手动写一遍。能更好理解。


结语

本文的很多内容都是借鉴于Android自定义控件三部曲文章,这个系列文章就像一本书一样,让我在学习自定义View的时候给了我很大的帮助。所以在我写的时候会借鉴很多他的内容。不过还是想我开头说的。学习自定义View是一个漫长的路。我也是边学边总结。我觉得要学好自定义View应该这样: 动画-->画笔-->画布-->View的绘制流程-->事件分发-->自定义View-->自定义布局-->drawable...这只是一个学习的过程,还需要大量的学习好的自定义View,还需多练习。并且深入了解某一个控件的属性。所以以后的文章我会把我学习到的都总结在这里希望和我一样的小白早日进阶。 下篇就来总结下属性动画。 最后,希望和我一样在严酷的市场环境下坚持做Android的小白一起加油。

优秀博客以及文章:

Android自定义控件三部曲文章 Android开发艺术探索 这本书我现在还没看是开只是大致阅读了下 发现里面涉及到大量的自定义View知识后续会总结精华提取到文章中 程序员的自我反思 他里面有许多关于自定义View的文章 带你一步步深入了解View Android 自定义控件之起步

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏walterlv - 吕毅的博客

WPF 绘制对齐像素的清晰显示的线条

发布于 2017-12-12 13:49 更新于 2018-08...

1191
来自专栏Coco的专栏

奇妙的 CSS shapes(CSS图形)

2185
来自专栏前端杂货铺

绝对定位下的盒模型

元素被绝对定位,那么元素将会脱离正常流(normal flow),并依据包含块来定位。包含块的概念及其判定可以看这里。 在负margin的应用一文中,我们提到了...

2364
来自专栏腾讯NEXT学位

我不知道你知不知道但前端NEXT知道的伪元素小技巧

3547
来自专栏何俊林

Android开发之贝塞尔曲线进阶篇(仿直播送礼物,饿了么购物车动画)

今天来自李晨玮分享的直播礼物效果Demo。对于直播中送车,点赞都有借鉴意义。李晨玮的简书为:http://www.jianshu.com/u/b2df0a5ea...

5028
来自专栏一个小程序员的成长笔记

CSS深入理解学习笔记之border

1、border-width   border-width为何不支持百分比:语义和使用场景决定的,现实中各种边框本身的概念就不存在百分比的使用方法。   bor...

3139
来自专栏贺贺的前端工程师之路

Flex Box布局学习- 语法

上一篇,我学习并整理了使用flex时,需要注意的兼容性问题。那么今天就来学习一下有关flex语法的东西。

773
来自专栏练小习的专栏

制作高大上的Canvas粒子动画

制作粒子动画效果要解决两个问题:一个是粒子动画轨迹,另外一个是粒子执行动画的时机。 首先来看下我们准备要做的粒子动画效果是怎么样的~ 是这样(粒子漂浮): ...

48410
来自专栏前端侠2.0

通过CSS,实现元素反转 原

      今天突然看到ES6还有Reflect 概念,我怎么以前没注意过,赶快去CANIUSE上查一下吧,却意外看到CSS Reflections,竟然可以有...

1591
来自专栏Android知识点总结

D6-Android绘图之一言不合画个表

1184

扫码关注云+社区