精华内容
参与话题
问答
  • 动画:用动画给面试官解释 TCP 三次握手过程

    万次阅读 多人点赞 2019-10-12 07:55:38
    来源 | 公众号:小鹿动画学编程 写在前边 TCP 三次握手过程对于面试是必考的一个,所以不但要掌握 TCP 整个握手的过程,其中有些小细节也更受到面试官的青睐。 对于这部分掌握以及 TCP 的四次挥手,小鹿将会以...

    在这里插入图片描述
    作者 | 小鹿
    来源 | 公众号:小鹿动画学编程


    写在前边

    TCP 三次握手过程对于面试是必考的一个,所以不但要掌握 TCP 整个握手的过程,其中有些小细节也更受到面试官的青睐。

    对于这部分掌握以及 TCP 的四次挥手,小鹿将会以动画的形式呈现给每个人,这样将复杂的知识简单化,理解起来也容易了很多,尤其对于一个初学者来说。


    学习导图

    在这里插入图片描述

    一、TCP 是什么?

    TCP(Transmission Control Protocol 传输控制协议)是一种面向连接的、可靠的、基于字节流的传输层通信协议。

    我们知道了上述了解到了 TCP 的定义,通俗一点的讲,TCP 就是一个双方通信的一个规范标准(协议)。

    我们在学习 TCP 握手过程之前,首先必须了解 TCP 报文头部的一些标志信息,因为在 TCP 握手的过程中,会使用到这些报文信息,如果没有掌握这些信息,在学习握手过程中,整个人处于懵逼状态,也是为了能够深入 TCP 三次握手的原理。


    二、TCP 头部报文

    在这里插入图片描述

    2.1 source portdestination port

    两者分别为「源端口号」和「目的端口号」。源端口号就是指本地端口,目的端口就是远程端口。

    一个数据包(pocket)被解封装成数据段(segment)后就会涉及到连接上层协议的端口问题。

    可以这么理解,我们可以想象发送方很多的窗户,接收方也有很多的窗户,这些窗口都标有不同的端口号,源端口号和目的端口号就分别代表从哪个规定的串口发送到对方接收的窗口。不同的应用程度都有着不同的端口,之前网络分层的文章中有提到过。
    在这里插入图片描述

    扩展:应用程序的端口号和应用程序所在主机的 IP 地址统称为 socket(套接字),IP:端口号, 在互联网上 socket 唯一标识每一个应用程序,源端口+源IP+目的端口+目的IP称为”套接字对“,一对套接字就是一个连接,一个客户端与服务器之间的连接。


    2.2 Sequence Numbe

    称为「序列号」。用于 TCP 通信过程中某一传输方向上字节流的每个字节的编号,为了确保数据通信的有序性,避免网络中乱序的问题。接收端根据这个编号进行确认,保证分割的数据段在原始数据包的位置。

    在这里插入图片描述
    再通俗一点的讲,每个字段在传送中用序列号来标记自己位置的,而这个字段就是用来完成双方传输中确保字段原始位置是按照传输顺序的。(发送方是数据是怎样一个顺序,到了接受方也要确保是这个顺序)

    PS:初始序列号由自己定,而后绪的序列号由对端的 ACK 决定:SN_x = ACK_y (x 的序列号 = y 发给 x 的 ACK),这里后边会讲到。


    2.3 Acknowledgment Numbe

    称为「确认序列号」。确认序列号是接收确认端所期望收到的下一序列号。确认序号应当是上次已成功收到数据字节序号加1,只有当标志位中的 ACK 标志为 1 时该确认序列号的字段才有效。主要用来解决不丢包的问题。

    若确认号=N,则表明:到序号N-1为止的所有数据都已正确收到。

    在这里,现在我们只需知道它的作用是什么,就是在数据传输的时候是一段一段的,都是由序列号进行标识的,所以说,接收端每接收一段,之后就想要的下一段的序列号就称为「确认序列号」。


    2.4 TCP Flag

    TCP 首部中有 6 个标志比特,它们中的多个可同时被设置为 1,主要是用于操控 TCP 的状态机的,依次为URG,ACK,PSH,RST,SYN,FIN

    不要求初学者全部掌握,在这里只讲三个重点的标志:


    2.4.1 ACK

    这个标识可以理解为发送端发送数据到接收端,发送的时候 ACK 为 0,标识接收端还未应答,一旦接收端接收数据之后,就将 ACK 置为 1,发送端接收到之后,就知道了接收端已经接收了数据。
    在这里插入图片描述

    此标志表示「应答域有效」,就是说前面所说的TCP应答号将会包含在 TCP 数据包中;有两个取值:0 和 1,为 1 的时候表示应答域有效,反之为 0;


    2.4.2 SYN

    表示「同步序列号」,是 TCP 握手的发送的第一个数据包。

    用来建立 TCP 的连接。SYN 标志位和 ACK 标志位搭配使用,当连接请求的时候,SYN=1,ACK=0连接被响应的时候,SYN=1,ACK=1;这个标志的数据包经常被用来进行端口扫描。扫描者发送一个只有 SYN 的数据包,如果对方主机响应了一个数据包回来 ,就表明这台主机存在这个端口。看下面动画:
    在这里插入图片描述

    2.4.3 FIN

    表示发送端已经达到数据末尾,也就是说双方的数据传送完成,没有数据可以传送了,发送FIN标志位的 TCP 数据包后,连接将被断开。这个标志的数据包也经常被用于进行端口扫描。

    这个很好理解,就是说,发送端只剩最后的一段数据了,同时要告诉接收端后边没有数据可以接受了,所以用FIN标识一下,接收端看到这个FIN之后,哦!这是接受的最后的数据,接受完就关闭了。动画如下:
    在这里插入图片描述

    2.5 Window size

    称为滑动窗口大小。所说的滑动窗口,用来进行流量控制。


    3、为什么进行 TCP 三次握手?

    如果之前你不了解网络分层的话,建议看看写的文章。

    你真的懂网络分层协议吗?

    第一,为了确认双方的接收与发送能力是否正常。第二,指定自己的初始化序列号,为后面的可靠传送做准备。第三,如果是 https 协议的话,三次握手这个过程,还会进行数字证书的验证以及加密密钥的生成到。

    如果你了解 UDP 的话,TCP 的出现正式弥补了 UDP 不可靠传输的缺点。但是 TCP 的诞生,也必然增加了连接的复杂性。


    4、TCP 三次握手过程?

    TCP 三次握手的过程掌握最重要的两点就是客户端和服务端状态的变化,另一个是三次握手过程标志信息的变化,那么掌握 TCP 的三次握手就简单多了。下面我们就以动画形式进行拆解三次握手过程。
    在这里插入图片描述

    • 初始状态:客户端处于 closed(关闭)状态,服务器处于 listen(监听) 状态。
      在这里插入图片描述
    • 第一次握手:客户端发送请求报文将 SYN = 1同步序列号和初始化序列号seq = x发送给服务端,发送完之后客户端处于SYN_Send状态。

    在这里插入图片描述

    • 第二次握手:服务端受到 SYN 请求报文之后,如果同意连接,会以自己的同步序列号SYN(服务端) = 1、初始化序列号 seq = y和确认序列号(期望下次收到的数据包)ack = x+ 1 以及确认号ACK = 1报文作为应答,服务器为SYN_Receive状态。

    在这里插入图片描述

    • 第三次握手: 客户端接收到服务端的 SYN + ACK之后,知道可以下次可以发送了下一序列的数据包了,然后发送同步序列号 ack = y + 1和数据包的序列号 seq = x + 1以及确认号ACK = 1确认包作为应答,客户端转为established状态。

    在这里插入图片描述

    5、为什么不是一次、二次握手?

    防止了服务器端的一直等待而浪费资源。

    为了防止已失效的连接请求报文段突然又传送到了服务端,因而产生错误。如果此时客户端发送的延迟的握手信息服务器收到,然后服务器进行响应,认为客户端要和它建立连接,此时客户端并没有这个意思,但 server 却以为新的运输连接已经建立,并一直等待 client 发来数据。这样,server 的很多资源就白白浪费掉了。


    ----------------------------------------------------------------------- 于2019/11/11 修改 ------------------------------------------------------------------
    主要对文章中存在的笔误和错误进行了修改,动画也进行了重新制作和修改,文章内容也进行的部分内容增加 —— 三次握手过程详细细节部分。再次感谢大家对小鹿文章的支持!

    下一篇:动画:用动画给女朋友讲解 TCP 四次分手过程


    福利:可以在我的公众号『小鹿动画学编程』,后台回复『资源』即可获取。

    ❤️ 不要忘记留下你学习的脚印 [点赞 + 收藏 + 评论]

    一些后台小伙伴问我平常如何学习的,学习资料哪里获取,我就不一一回复了!一般我都是通过看一些编程书籍和开源的社区进行自学,一些学习资料和电子书也分享到下边了,有需要的自取。

    编程在于永无止境的去学习,去学习前辈积累的经验,书籍就是最好的一种媒介方式,列出以下自己看过的优秀书籍,整理成了 PDF 版。

    • 前端:《javascript高级程序设计》《JavaScript 权威指南》《你不知道的JavaScript(上中下卷)》等;
    • java:《Effective Java》《Thinking in Java》《Java 编程思想》《java核心技术》等;
    • 算法:《大话数据结构》《算法图解》《算法导论》《编程之美》《数据结构与算法:C语言描述》等;
    • 其他相关计算机书籍;

    搜索我的公众号:「小鹿动画学编程」后台回复关键词

    • 回复「后台」,获取 java 等自学资料
    • 回复「前端」,获取前端等自学资料
    • 回复「电子书」获取一下书籍资料!

    动一动你的小手,点赞就完事了,每个人出一份力量(点赞 + 评论)就会让更多的学习者加入进来!非常感谢! ̄ω ̄=


    作者Info:

    【作者】:小鹿

    【原创公众号】:小鹿动画学编程。

    【简介】:和小鹿同学一起用动画的方式从零基础学编程,将 Web前端领域、数据结构与算法、网络原理等通俗易懂的呈献给小伙伴。先定个小目标,原创 1000 篇的动画技术文章,和各位小伙伴共同努力一起学习!公众号回复 “资料” 送一从零自学资料大礼包!

    【转载说明】:转载请说明出处,谢谢合作!~

    展开全文
  • 自定义动画 <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>动画</...

    自定义动画

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>动画</title>
        <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
        <style>
            p{
    			width: 300px;
    			height: 300px;
    			background-color:red;
    		}
            .test-enter-active,.test-leave-active{
    			transition:all 2s ease;
    		}
    		.test-enter-active{
    			opacity:1;
    			width:300px;
    			height:300px;
    		}
    		.test-leave-active{
    			opacity:0;
    			width:50px;
    			height:50px;
    		}
    		/* .fade-enter需要放在.fade-enter-active的后面 */
    		.test-enter{
    			opacity:0;
    			width: 10px;
    			height: 10px;
    		}
        </style>
    </head>
    <body>
        <div id="itapp">
            <button @click="flag=!flag">点我</button>
            <transition name="test" 
                @before-enter="beforeEnter"
    			@enter="enter"
    			@after-enter="afterEnter"
    			@before-leave="beforeLeave"
    			@leave="leave"
    			@after-leave="afterLeave">
                <p v-show="flag"
                >动画</p>
            </transition>  
        </div>
        <script>
            var vm = new Vue({
                data(){
                    return {
                        flag:false
                    }
                },
                el:'#itapp',
                methods:{
                    beforeEnter(){
                        console.log('动画进入之前');
                    },
                    enter(){
                        console.log('动画进入');
                    },
                    afterEnter(el){
                        console.log('动画进入之后');
                        el.style.background='blue';
                    },
                    beforeLeave(){
                        console.log('动画离开之前');
                    },
                    leave(){
                        console.log('动画离开');
                    },
                    afterLeave(){
                        console.log('动画离开之后');
                    }
                }
               
            })
        </script>
    </body>
    </html>
    
    

    css3动画库得引用animate.css的使用

    <!DOCTYPE html>
    <html lang="en">
    <head>
    	<meta charset="UTF-8">
    	<title>动画</title>
    	<link rel="stylesheet" href="https://cdn.bootcdn.net/ajax/libs/animate.css/3.7.2/animate.min.css">
    	<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
    	<style>
    		p{
    			width: 300px;
    			height: 300px;
    			background-color:red;
    			margin:0 auto;
    		}
    	</style>
    </head>
    <body>
    	<div id="app">
    		<button @click="flag=!flag">点我</button>
    		
    		<transition enter-active-class="animated bounceInDown" leave-active-class="animated fadeOut">
    			<p v-show="flag">动画内容</p>
    		</transition>
    	</div>
    
    	<script>
    		var vm=new Vue({
    			el:'#app',
    			data:{
    				flag:false
    			}
    		});
    	</script>
    	
    </body>
    </html>
    
    

    动画组的使用

    <!DOCTYPE html>
    <html lang="en">
    <head>
    	<meta charset="UTF-8">
    	<title>多元素动画</title>
    	<link rel="stylesheet" href="https://cdn.bootcdn.net/ajax/libs/animate.css/3.7.2/animate.min.css">
    	<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
    	<style>
    		p{
    			width: 100px;
    			height: 100px;
    			background-color:red;
    			margin:20px auto;
    		}
    	</style>
    </head>
    <body>
    	<div id="itapp">
    		<button @click="flag=!flag">点我</button>
    		
    		<transition-group enter-active-class="animated bounceInLeft" leave-active-class="animated bounceOutRight">
    			<!-- 内部元素 总是需要 提供唯一的 key 属性值 -->
    			<p v-show="flag" :key="1">itapp</p>
    			<p v-show="flag" :key="2">软谋</p>
    		</transition-group>
    	</div>
    
    	<script>
    		var vm=new Vue({
    			el:'#itapp',
    			data:{
    				flag:false
    			}
    		});
    	</script>
    	
    </body>
    </html>
    
    
    展开全文
  • c语言字符动画的实现

    千次阅读 多人点赞 2018-12-04 21:15:43
    对于此次c语言动画的实现,思路很简单,先从网上下载一段mv及原声音乐,用DVDVideoSoft Free Studio将视频分为3000张图片,再用Ascgen2将3000张图片转化问3000个ASCII字符txt文件,并保持像素的一致,然后通过程序...

    原文链接: http://www.diein1998.top

    • 实现过程:

    对于此次c语言动画的实现,思路很简单,先从网上下载一段mv及原声音乐,用DVDVideoSoft Free Studio将视频分为3000张图片,再用Ascgen2将3000张图片转化问3000个ASCII字符txt文件,并保持像素的一致,然后通过程序调用每一个文本并快速清屏通过快速切换在控制台来实现动画效果。

    二、源代码

    #include<windows.h>

    #include <mmsystem.h>

    #pragma comment(lib, "winmm")

    #include<stdio.h>

    #include<stdlib.h>

    #include<string.h>

    #include<conio.h>                   

    #define WIDTH 474 //宽度

    #define HIGHT 120 //高度

    #define PAGE_LIMIT 3000         //帧数

    #define N HIGHT*WIDTH           //字符数

    //初命名

    char name[]="ASCII-1 0001.txt";

    char str[N];

    int main()

    {

          system("pause");//等待用户信号;

          int i,j,n=1,p,q;

          char a[4]="000";

          //帧操作

          for(i=1;i<=PAGE_LIMIT;i++)

          {

                //时间轴定位

                for(p=10,q=0;q<4;q++)

                {

                      if(i<10&&q==1)break;

                      else if(i<100&&q==2)break;

                      else if(i<1000&&q==3)break;

                      else

                      {

                           a[q]=i%p/(p/10)+48;

                           p*=10; 

                      }

                }

                //重命名

                for(p=0;p<q;p++)

                      name[11-p]=a[p];

                FILE *fp;

                //打开文本

                if((fp=fopen(name,"r"))==NULL)  

                {

                      printf("%d",i);

                      system("pause");

                      continue;

                }

                //读取文本

                while(fgets(str,N ,fp)!=NULL)

                      printf("%s",str);

                //关闭文本

                fclose(fp);

                system("cls");//清屏

          }

          system("pause");//等待用户信号

          return 0;

    }

    展开全文
  • Android动画效果集合开源APP(BaseAnimation1.3)程序源码

    千次下载 热门讨论 2014-02-10 20:31:35
    BaseAnimation1.3版本增加如下动画 1.Splash增加2个动画 2.高仿动画效果增加10个 3.ListView集合增加15个 4.自定义控件集合增加17个 5.页面滑动增加4个 共增加48个动画效果 下载app源码的朋友需要把 BAnim ...
  • 在手机上去实现一些动画效果算是件比较炫酷的事情,因此Android系统在一开始的时候就给我们提供了两种实现动画效果的方式,逐帧动画(frame-by-frame animation)和补间动画(tweened animation)。逐帧动画的工作原理很...

    转载请注明出处:http://blog.csdn.net/guolin_blog/article/details/43536355


    在手机上去实现一些动画效果算是件比较炫酷的事情,因此Android系统在一开始的时候就给我们提供了两种实现动画效果的方式,逐帧动画(frame-by-frame animation)和补间动画(tweened animation)。逐帧动画的工作原理很简单,其实就是将一个完整的动画拆分成一张张单独的图片,然后再将它们连贯起来进行播放,类似于动画片的工作原理。补间动画则是可以对View进行一系列的动画操作,包括淡入淡出、缩放、平移、旋转四种。


    然而自Android 3.0版本开始,系统给我们提供了一种全新的动画模式,属性动画(property animation),它的功能非常强大,弥补了之前补间动画的一些缺陷,几乎是可以完全替代掉补间动画了。对于逐帧动画和补间动画的用法,我不想再多讲,它们的技术已经比较老了,而且网上资料也非常多,那么今天我们这篇文章的主题就是对Android属性动画进行一次完全解析。


    为什么要引入属性动画?


    Android之前的补间动画机制其实还算是比较健全的,在android.view.animation包下面有好多的类可以供我们操作,来完成一系列的动画效果,比如说对View进行移动、缩放、旋转和淡入淡出,并且我们还可以借助AnimationSet来将这些动画效果组合起来使用,除此之外还可以通过配置Interpolator来控制动画的播放速度等等等等。那么这里大家可能要产生疑问了,既然之前的动画机制已经这么健全了,为什么还要引入属性动画呢?


    其实上面所谓的健全都是相对的,如果你的需求中只需要对View进行移动、缩放、旋转和淡入淡出操作,那么补间动画确实已经足够健全了。但是很显然,这些功能是不足以覆盖所有的场景的,一旦我们的需求超出了移动、缩放、旋转和淡入淡出这四种对View的操作,那么补间动画就不能再帮我们忙了,也就是说它在功能和可扩展方面都有相当大的局限性,那么下面我们就来看看补间动画所不能胜任的场景。


    注意上面我在介绍补间动画的时候都有使用“对View进行操作”这样的描述,没错,补间动画是只能够作用在View上的。也就是说,我们可以对一个Button、TextView、甚至是LinearLayout、或者其它任何继承自View的组件进行动画操作,但是如果我们想要对一个非View的对象进行动画操作,抱歉,补间动画就帮不上忙了。可能有的朋友会感到不能理解,我怎么会需要对一个非View的对象进行动画操作呢?这里我举一个简单的例子,比如说我们有一个自定义的View,在这个View当中有一个Point对象用于管理坐标,然后在onDraw()方法当中就是根据这个Point对象的坐标值来进行绘制的。也就是说,如果我们可以对Point对象进行动画操作,那么整个自定义View的动画效果就有了。显然,补间动画是不具备这个功能的,这是它的第一个缺陷。


    然后补间动画还有一个缺陷,就是它只能够实现移动、缩放、旋转和淡入淡出这四种动画操作,那如果我们希望可以对View的背景色进行动态地改变呢?很遗憾,我们只能靠自己去实现了。说白了,之前的补间动画机制就是使用硬编码的方式来完成的,功能限定死就是这些,基本上没有任何扩展性可言。


    最后,补间动画还有一个致命的缺陷,就是它只是改变了View的显示效果而已,而不会真正去改变View的属性。什么意思呢?比如说,现在屏幕的左上角有一个按钮,然后我们通过补间动画将它移动到了屏幕的右下角,现在你可以去尝试点击一下这个按钮,点击事件是绝对不会触发的,因为实际上这个按钮还是停留在屏幕的左上角,只不过补间动画将这个按钮绘制到了屏幕的右下角而已。


    也正是因为这些原因,Android开发团队决定在3.0版本当中引入属性动画这个功能,那么属性动画是不是就把上述的问题全部解决掉了?下面我们就来一起看一看。


    新引入的属性动画机制已经不再是针对于View来设计的了,也不限定于只能实现移动、缩放、旋转和淡入淡出这几种动画操作,同时也不再只是一种视觉上的动画效果了。它实际上是一种不断地对值进行操作的机制,并将值赋值到指定对象的指定属性上,可以是任意对象的任意属性。所以我们仍然可以将一个View进行移动或者缩放,但同时也可以对自定义View中的Point对象进行动画操作了。我们只需要告诉系统动画的运行时长,需要执行哪种类型的动画,以及动画的初始值和结束值,剩下的工作就可以全部交给系统去完成了。


    既然属性动画的实现机制是通过对目标对象进行赋值并修改其属性来实现的,那么之前所说的按钮显示的问题也就不复存在了,如果我们通过属性动画来移动一个按钮,那么这个按钮就是真正的移动了,而不再是仅仅在另外一个位置绘制了而已。


    好了,介绍了这么多,相信大家已经对属性动画有了一个最基本的认识了,下面我们就来开始学习一下属性动画的用法。


    ValueAnimator


    ValueAnimator是整个属性动画机制当中最核心的一个类,前面我们已经提到了,属性动画的运行机制是通过不断地对值进行操作来实现的,而初始值和结束值之间的动画过渡就是由ValueAnimator这个类来负责计算的。它的内部使用一种时间循环的机制来计算值与值之间的动画过渡,我们只需要将初始值和结束值提供给ValueAnimator,并且告诉它动画所需运行的时长,那么ValueAnimator就会自动帮我们完成从初始值平滑地过渡到结束值这样的效果。除此之外,ValueAnimator还负责管理动画的播放次数、播放模式、以及对动画设置监听器等,确实是一个非常重要的类。


    但是ValueAnimator的用法却一点都不复杂,我们先从最简单的功能看起吧,比如说想要将一个值从0平滑过渡到1,时长300毫秒,就可以这样写:

    ValueAnimator anim = ValueAnimator.ofFloat(0f, 1f);
    anim.setDuration(300);
    anim.start();

    怎么样?很简单吧,调用ValueAnimator的ofFloat()方法就可以构建出一个ValueAnimator的实例,ofFloat()方法当中允许传入多个float类型的参数,这里传入0和1就表示将值从0平滑过渡到1,然后调用ValueAnimator的setDuration()方法来设置动画运行的时长,最后调用start()方法启动动画。


    用法就是这么简单,现在如果你运行一下上面的代码,动画就会执行了。可是这只是一个将值从0过渡到1的动画,又看不到任何界面效果,我们怎样才能知道这个动画是不是已经真正运行了呢?这就需要借助监听器来实现了,如下所示:

    ValueAnimator anim = ValueAnimator.ofFloat(0f, 1f);
    anim.setDuration(300);
    anim.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
        @Override
        public void onAnimationUpdate(ValueAnimator animation) {
            float currentValue = (float) animation.getAnimatedValue();
            Log.d("TAG", "cuurent value is " + currentValue);
        }
    });
    anim.start();

    可以看到,这里我们通过addUpdateListener()方法来添加一个动画的监听器,在动画执行的过程中会不断地进行回调,我们只需要在回调方法当中将当前的值取出并打印出来,就可以知道动画有没有真正运行了。运行上述代码,控制台打印如下所示:




    从打印日志的值我们就可以看出,ValueAnimator确实已经在正常工作了,值在300毫秒的时间内从0平滑过渡到了1,而这个计算工作就是由ValueAnimator帮助我们完成的。另外ofFloat()方法当中是可以传入任意多个参数的,因此我们还可以构建出更加复杂的动画逻辑,比如说将一个值在5秒内从0过渡到5,再过渡到3,再过渡到10,就可以这样写:

    ValueAnimator anim = ValueAnimator.ofFloat(0f, 5f, 3f, 10f);
    anim.setDuration(5000);
    anim.start();
    当然也许你并不需要小数位数的动画过渡,可能你只是希望将一个整数值从0平滑地过渡到100,那么也很简单,只需要调用ValueAnimator的ofInt()方法就可以了,如下所示:
    ValueAnimator anim = ValueAnimator.ofInt(0, 100);

    ValueAnimator当中最常用的应该就是ofFloat()和ofInt()这两个方法了,另外还有一个ofObject()方法,我会在下篇文章进行讲解。


    那么除此之外,我们还可以调用setStartDelay()方法来设置动画延迟播放的时间,调用setRepeatCount()和setRepeatMode()方法来设置动画循环播放的次数以及循环播放的模式,循环模式包括RESTART和REVERSE两种,分别表示重新播放和倒序播放的意思。这些方法都很简单,我就不再进行详细讲解了。


    ObjectAnimator


    相比于ValueAnimator,ObjectAnimator可能才是我们最常接触到的类,因为ValueAnimator只不过是对值进行了一个平滑的动画过渡,但我们实际使用到这种功能的场景好像并不多。而ObjectAnimator则就不同了,它是可以直接对任意对象的任意属性进行动画操作的,比如说View的alpha属性。


    不过虽说ObjectAnimator会更加常用一些,但是它其实是继承自ValueAnimator的,底层的动画实现机制也是基于ValueAnimator来完成的,因此ValueAnimator仍然是整个属性动画当中最核心的一个类。那么既然是继承关系,说明ValueAnimator中可以使用的方法在ObjectAnimator中也是可以正常使用的,它们的用法也非常类似,这里如果我们想要将一个TextView在5秒中内从常规变换成全透明,再从全透明变换成常规,就可以这样写:

    ObjectAnimator animator = ObjectAnimator.ofFloat(textview, "alpha", 1f, 0f, 1f);
    animator.setDuration(5000);
    animator.start();

    可以看到,我们还是调用了ofFloat()方法来去创建一个ObjectAnimator的实例,只不过ofFloat()方法当中接收的参数有点变化了。这里第一个参数要求传入一个object对象,我们想要对哪个对象进行动画操作就传入什么,这里我传入了一个textview。第二个参数是想要对该对象的哪个属性进行动画操作,由于我们想要改变TextView的不透明度,因此这里传入"alpha"。后面的参数就是不固定长度了,想要完成什么样的动画就传入什么值,这里传入的值就表示将TextView从常规变换成全透明,再从全透明变换成常规。之后调用setDuration()方法来设置动画的时长,然后调用start()方法启动动画,效果如下图所示:




    学会了这一个用法之后,其它的用法我们就可以举一反三了,那比如说我们想要将TextView进行一次360度的旋转,就可以这样写:

    ObjectAnimator animator = ObjectAnimator.ofFloat(textview, "rotation", 0f, 360f);
    animator.setDuration(5000);
    animator.start();

    可以看到,这里我们将第二个参数改成了"rotation",然后将动画的初始值和结束值分别设置成0和360,现在运行一下代码,效果如下图所示:




    那么如果想要将TextView先向左移出屏幕,然后再移动回来,就可以这样写:

    float curTranslationX = textview.getTranslationX();
    ObjectAnimator animator = ObjectAnimator.ofFloat(textview, "translationX", curTranslationX, -500f, curTranslationX);
    animator.setDuration(5000);
    animator.start();

    这里我们先是调用了TextView的getTranslationX()方法来获取到当前TextView的translationX的位置,然后ofFloat()方法的第二个参数传入"translationX",紧接着后面三个参数用于告诉系统TextView应该怎么移动,现在运行一下代码,效果如下图所示:




    然后我们还可以TextView进行缩放操作,比如说将TextView在垂直方向上放大3倍再还原,就可以这样写:

    ObjectAnimator animator = ObjectAnimator.ofFloat(textview, "scaleY", 1f, 3f, 1f);
    animator.setDuration(5000);
    animator.start();

    这里将ofFloat()方法的第二个参数改成了"scaleY",表示在垂直方向上进行缩放,现在重新运行一下程序,效果如下图所示:




    到目前为止,ObjectAnimator的用法还算是相当简单吧,但是我相信肯定会有不少朋友现在心里都有同样一个疑问,就是ofFloat()方法的第二个参数到底可以传哪些值呢?目前我们使用过了alpha、rotation、translationX和scaleY这几个值,分别可以完成淡入淡出、旋转、水平移动、垂直缩放这几种动画,那么还有哪些值是可以使用的呢?其实这个问题的答案非常玄乎,就是我们可以传入任意的值到ofFloat()方法的第二个参数当中。任意的值?相信这很出乎大家的意料吧,但事实就是如此。因为ObjectAnimator在设计的时候就没有针对于View来进行设计,而是针对于任意对象的,它所负责的工作就是不断地向某个对象中的某个属性进行赋值,然后对象根据属性值的改变再来决定如何展现出来。


    那么比如说我们调用下面这样一段代码:

    ObjectAnimator.ofFloat(textview, "alpha", 1f, 0f);

    其实这段代码的意思就是ObjectAnimator会帮我们不断地改变textview对象中alpha属性的值,从1f变化到0f。然后textview对象需要根据alpha属性值的改变来不断刷新界面的显示,从而让用户可以看出淡入淡出的动画效果。


    那么textview对象中是不是有alpha属性这个值呢?没有,不仅textview没有这个属性,连它所有的父类也是没有这个属性的!这就奇怪了,textview当中并没有alpha这个属性,ObjectAnimator是如何进行操作的呢?其实ObjectAnimator内部的工作机制并不是直接对我们传入的属性名进行操作的,而是会去寻找这个属性名对应的get和set方法,因此alpha属性所对应的get和set方法应该就是:

    public void setAlpha(float value);
    public float getAlpha();

    那么textview对象中是否有这两个方法呢?确实有,并且这两个方法是由View对象提供的,也就是说不仅TextView可以使用这个属性来进行淡入淡出动画操作,任何继承自View的对象都可以的。


    既然alpha是这个样子,相信大家一定已经明白了,前面我们所用的所有属性都是这个工作原理,那么View当中一定也存在着setRotation()、getRotation()、setTranslationX()、getTranslationX()、setScaleY()、getScaleY()这些方法,不信的话你可以到View当中去找一下。


    组合动画


    独立的动画能够实现的视觉效果毕竟是相当有限的,因此将多个动画组合到一起播放就显得尤为重要。幸运的是,Android团队在设计属性动画的时候也充分考虑到了组合动画的功能,因此提供了一套非常丰富的API来让我们将多个动画组合到一起。


    实现组合动画功能主要需要借助AnimatorSet这个类,这个类提供了一个play()方法,如果我们向这个方法中传入一个Animator对象(ValueAnimator或ObjectAnimator)将会返回一个AnimatorSet.Builder的实例,AnimatorSet.Builder中包括以下四个方法:

    • after(Animator anim)   将现有动画插入到传入的动画之后执行
    • after(long delay)   将现有动画延迟指定毫秒后执行
    • before(Animator anim)   将现有动画插入到传入的动画之前执行
    • with(Animator anim)   将现有动画和传入的动画同时执行

    好的,有了这四个方法,我们就可以完成组合动画的逻辑了,那么比如说我们想要让TextView先从屏幕外移动进屏幕,然后开始旋转360度,旋转的同时进行淡入淡出操作,就可以这样写:

    ObjectAnimator moveIn = ObjectAnimator.ofFloat(textview, "translationX", -500f, 0f);
    ObjectAnimator rotate = ObjectAnimator.ofFloat(textview, "rotation", 0f, 360f);
    ObjectAnimator fadeInOut = ObjectAnimator.ofFloat(textview, "alpha", 1f, 0f, 1f);
    AnimatorSet animSet = new AnimatorSet();
    animSet.play(rotate).with(fadeInOut).after(moveIn);
    animSet.setDuration(5000);
    animSet.start();

    可以看到,这里我们先是把三个动画的对象全部创建出来,然后new出一个AnimatorSet对象之后将这三个动画对象进行播放排序,让旋转和淡入淡出动画同时进行,并把它们插入到了平移动画的后面,最后是设置动画时长以及启动动画。运行一下上述代码,效果如下图所示:




    Animator监听器


    在很多时候,我们希望可以监听到动画的各种事件,比如动画何时开始,何时结束,然后在开始或者结束的时候去执行一些逻辑处理。这个功能是完全可以实现的,Animator类当中提供了一个addListener()方法,这个方法接收一个AnimatorListener,我们只需要去实现这个AnimatorListener就可以监听动画的各种事件了。


    大家已经知道,ObjectAnimator是继承自ValueAnimator的,而ValueAnimator又是继承自Animator的,因此不管是ValueAnimator还是ObjectAnimator都是可以使用addListener()这个方法的。另外AnimatorSet也是继承自Animator的,因此addListener()这个方法算是个通用的方法。


    添加一个监听器的代码如下所示:

    anim.addListener(new AnimatorListener() {
    	@Override
    	public void onAnimationStart(Animator animation) {
    	}
    
    	@Override
    	public void onAnimationRepeat(Animator animation) {
    	}
    
    	@Override
    	public void onAnimationEnd(Animator animation) {
    	}
    
    	@Override
    	public void onAnimationCancel(Animator animation) {
    	}
    });

    可以看到,我们需要实现接口中的四个方法,onAnimationStart()方法会在动画开始的时候调用,onAnimationRepeat()方法会在动画重复执行的时候调用,onAnimationEnd()方法会在动画结束的时候调用,onAnimationCancel()方法会在动画被取消的时候调用。


    但是也许很多时候我们并不想要监听那么多个事件,可能我只想要监听动画结束这一个事件,那么每次都要将四个接口全部实现一遍就显得非常繁琐。没关系,为此Android提供了一个适配器类,叫作AnimatorListenerAdapter,使用这个类就可以解决掉实现接口繁琐的问题了,如下所示:

    anim.addListener(new AnimatorListenerAdapter() {
    });
    这里我们向addListener()方法中传入这个适配器对象,由于AnimatorListenerAdapter中已经将每个接口都实现好了,所以这里不用实现任何一个方法也不会报错。那么如果我想监听动画结束这个事件,就只需要单独重写这一个方法就可以了,如下所示:
    anim.addListener(new AnimatorListenerAdapter() {
    	@Override
    	public void onAnimationEnd(Animator animation) {
    	}
    });


    使用XML编写动画


    我们可以使用代码来编写所有的动画功能,这也是最常用的一种做法。不过,过去的补间动画除了使用代码编写之外也是可以使用XML编写的,因此属性动画也提供了这一功能,即通过XML来完成和代码一样的属性动画功能。


    通过XML来编写动画可能会比通过代码来编写动画要慢一些,但是在重用方面将会变得非常轻松,比如某个将通用的动画编写到XML里面,我们就可以在各个界面当中轻松去重用它。


    如果想要使用XML来编写动画,首先要在res目录下面新建一个animator文件夹,所有属性动画的XML文件都应该存放在这个文件夹当中。然后在XML文件中我们一共可以使用如下三种标签:

    • <animator>  对应代码中的ValueAnimator
    • <objectAnimator>  对应代码中的ObjectAnimator
    • <set>  对应代码中的AnimatorSet

    那么比如说我们想要实现一个从0到100平滑过渡的动画,在XML当中就可以这样写:

    <animator xmlns:android="http://schemas.android.com/apk/res/android"
        android:valueFrom="0"
        android:valueTo="100"
        android:valueType="intType"/>
    而如果我们想将一个视图的alpha属性从1变成0,就可以这样写:
    <objectAnimator xmlns:android="http://schemas.android.com/apk/res/android"
        android:valueFrom="1"
        android:valueTo="0"
        android:valueType="floatType"
        android:propertyName="alpha"/>
    其实XML编写动画在可读性方面还是挺高的,上面的内容相信不用我做解释大家也都看得懂吧。


    另外,我们也可以使用XML来完成复杂的组合动画操作,比如将一个视图先从屏幕外移动进屏幕,然后开始旋转360度,旋转的同时进行淡入淡出操作,就可以这样写:

    <set xmlns:android="http://schemas.android.com/apk/res/android"
        android:ordering="sequentially" >
    
        <objectAnimator
            android:duration="2000"
            android:propertyName="translationX"
            android:valueFrom="-500"
            android:valueTo="0"
            android:valueType="floatType" >
        </objectAnimator>
    
        <set android:ordering="together" >
            <objectAnimator
                android:duration="3000"
                android:propertyName="rotation"
                android:valueFrom="0"
                android:valueTo="360"
                android:valueType="floatType" >
            </objectAnimator>
    
            <set android:ordering="sequentially" >
                <objectAnimator
                    android:duration="1500"
                    android:propertyName="alpha"
                    android:valueFrom="1"
                    android:valueTo="0"
                    android:valueType="floatType" >
                </objectAnimator>
                <objectAnimator
                    android:duration="1500"
                    android:propertyName="alpha"
                    android:valueFrom="0"
                    android:valueTo="1"
                    android:valueType="floatType" >
                </objectAnimator>
            </set>
        </set>
    
    </set>
    这段XML实现的效果和我们刚才通过代码来实现的组合动画的效果是一模一样的,每个参数的含义都非常清楚,相信大家都是一看就懂,我就不再一一解释了。


    最后XML文件是编写好了,那么我们如何在代码中把文件加载进来并将动画启动呢?只需调用如下代码即可:

    Animator animator = AnimatorInflater.loadAnimator(context, R.animator.anim_file);
    animator.setTarget(view);
    animator.start();
    调用AnimatorInflater的loadAnimator来将XML动画文件加载进来,然后再调用setTarget()方法将这个动画设置到某一个对象上面,最后再调用start()方法启动动画就可以了,就是这么简单。


    好的,通过本篇文章的学习,我相信大家已经对属性动画的基本用法已经有了一个相当不错的认识,并把最常用的一些功能都掌握好了,那么本篇文章的内容就到这里,下篇文章当中会继续介绍属性动画,讲解ValueAnimator和ObjectAnimator的高级用法,感兴趣的朋友请继续阅读 Android属性动画完全解析(中),ValueAnimator和ObjectAnimator的高级用法 。


    关注我的技术公众号,每天都有优质技术文章推送。关注我的娱乐公众号,工作、学习累了的时候放松一下自己。

    微信扫一扫下方二维码即可关注:

            

    展开全文
  • 程序员爱情表白专用html5动画网页的代码 下载地址:源码   程序猿表白专用的html5动画特效网页,真的挺羡慕创作者的水平,有这水平可以把爱表白给想表白的人,不要以为那些鲜花是用 的图片,你会发现在资源...
  • 动画:用动画给女朋友讲解 TCP 四次分手过程

    万次阅读 多人点赞 2019-10-21 07:57:56
    大家好,我们又见面了,做为一个业余的动画师,上次的用动画的形式讲解 TCP 三次握手过程再各大平台收到了广大读者的喜爱,说文章有趣、有货、有内容,也受到了很多读者的关注。很多读者留言说什么时候用动画讲一讲 ...
  • 属性动画的出现,弥补了补间动画的不足之处,补间动画,只是改变了表面上的东西,但是其中属性并未改变,而属性动画相反,改变了表面上的东西,并且也更改了其属性。 类:ObjectAnimator 用于操作属性动画的类 ...
  • 作者:Jonathan Saring 译者:前端小智 来源:medium . 为了保证的可读性,本文采用意译而非直译。 1.Three.js 超过46K的星星,这个流行的库提供了非常多的3D显示功能,以一种直观的方式使用 WebGL。...
  • 属性动画的出现,弥补了补间动画的不足之处,补间动画,只是改变了表面上的东西,但是其中属性并未改变,而属性动画相反,改变了表面上的东西,并且也更改了其属性。 类:ObjectAnimator 用于操作属性动画的类 ...
  • Python初探:turtle(海龟)实现动画

    千次阅读 2019-03-28 21:35:51
    利用Python的turtle库实现一个动画 Turtle库是Python内置的图形化模块,是绘制图像的函数库。海龟即屏幕上绘图的光标(小三角形),编写Python指令可以让海龟在屏幕上移动绘制线条,可将海龟看做是坐标系里移动,...
  • Android 安卓动画 补间动画 - 缩放动画

    千次阅读 多人点赞 2018-08-31 19:36:54
    补间动画之缩放动画 实现效果:点击按钮后实现按钮放大效果 补间动画概念:就是从一个画面过渡到另一个画面时让人看到中间动画效果! 动画 - 相关文章篇 帧动画动画: ...
  • 首先对动画制作感兴趣,每一个动画都像策划并拍了一场电影!Flash(Adobe Animate)动画制作入门视频教程,该视频课程适合初级入门,教会你动画原理! 分享是一种快乐!此视频是面授课程随堂录制视频,画面截图捕捉...
  • HTML5浪漫爱心表白动画在线演示程序

    万次下载 热门讨论 2014-02-12 23:50:10
    HTML5浪漫爱心表白动画在线演示.htm 修改一下情人节送女友
  • Android动画集合开源APP

    千次下载 热门讨论 2014-01-13 22:56:25
    BaseAnimation,如果有新版本会自动提醒大家更新,也希望大家多多贡献自己的动画xml文件或者其他源码,一起来打造这个开源的app 博客地址:http://blog.csdn.net/duguang77/article/details/18230867
  • 前言:这几天做客户回访,感触很大,用户只要是留反馈信息,总是一种恨铁不成钢的心态,想用你的app,却是因为你的技术问题,让他们不得不放弃,而你一个回访电话却让他们尽释前嫌,当最后把手机号留给他们以便随时...
  • 属性动画的出现,弥补了补间动画的不足之处,补间动画,只是改变了表面上的东西,但是其中属性并未改变,而属性动画相反,改变了表面上的东西,并且也更改了其属性。 类:ObjectAnimator 用于操作属性动画的类 ...
  • 属性动画的出现,弥补了补间动画的不足之处,补间动画,只是改变了表面上的东西,但是其中属性并未改变,而属性动画相反,改变了表面上的东西,并且也更改了其属性。 类:ObjectAnimator 用于操作属性动画的类 ...
  • Android动画之视图动画和属性动画

    千次阅读 2016-05-13 16:19:37
    Android 动画分为两大类,分别是视图动画(View Animation)和属性动画(Property Animation)。对于这两种动画,都能够使用xml和代码的形式定义动画。View Animation视图动画是Android最基础的动画,在API 1中就...
  • >Android中常用的动画都在这里了,包含了基本的动画【透明度动画,缩放动画,旋转动画,位移动画】;还有就是这四种动画的组合实现; 还有布局动画,就是在加载布局时的动画;还有Activity跳转的动画
  • 属性动画的出现,弥补了补间动画的不足之处,补间动画,只是改变了表面上的东西,但是其中属性并未改变,而属性动画相反,改变了表面上的东西,并且也更改了其属性。 类:ObjectAnimator 用于操作属性动画的类 ...
  • 利用MATLAB实现图片切换动画效果详解

    万次阅读 多人点赞 2018-03-15 16:59:51
    内容摘要:本博文介绍MATLAB图片切换动画效果的制作以及GIF文件保存,并结合具体代码详细解释。介绍了利用MATLAB编程进行几幅图片的轮流切换,切换时实现与幻灯片切换相似的炫酷的图片切换特效。其中涉及一些MATLAB...
  • 补间动画之平移动画 实现效果:点击按钮后旋转这个按钮 补间动画概念:就是从一个画面过渡到另一个画面时让人看到中间动画效果! 动画 - 相关文章篇 帧动画动画: ...
  • Android 属性动画(Property Animation) 完全解析 (上)

    万次阅读 多人点赞 2014-07-25 09:34:10
    转载请标明出处:http://blog.csdn.net/lmj623565791/article/details/380674751、概述Android提供了几种...View Animation相当简单,不过只能支持简单的缩放、平移、旋转、透明度基本的动画,且有一定的局限性。比如
  • 顾名思义,就是四种动画(平移动画,旋转动画,缩放动画,渐变动画)一起实现效果,四种动画有着共同的属性,也有各自的特有属性,下面列出来的四种动画的共有属性 实现目标:点击按钮后 四种动画(平移动画,旋转动画...
  • Android 动画:手把手教你使用 补间动画 (视图动画)

    万次阅读 多人点赞 2017-06-01 08:21:22
    可是动画的种类繁多、使用复杂,每当需要 采用自定义动画 实现 复杂的动画效果时,很多开发者就显得束手无策 本文将详细介绍 Android 动画中 补间动画的原理 & 使用 学习Android 动画最好先了解:自定义View的原理,...
  • 今天我们主要来模仿一下美团中加载数据时小人奔跑的效果,取个有趣的名字就是Running Man,奔跑吧,兄弟!
  • Android开发——View动画、帧动画和属性动画详解

    万次阅读 多人点赞 2016-10-02 19:28:10
    我们都知道Android动画分为三类:View动画、帧动画和属性动画。先对这三种动画做一个概述。View动画是一种渐进式动画,通过图像的平移、缩放、旋转和透明度等各种渐进式变换完成动画效果。帧动画是通过不停的切换...
  • unity3d 动画卡帧 动画合成 动画层次

    千次阅读 2013-02-26 16:22:12
    unity3d 中动画的添加 http://unity3d.com/support/documentation/Manual/Character-Animation.html#AnimLayers 在unity3d中,我们能很方便的使用4个动画,默认的是走,跑,跳,待机动作,可当...

空空如也

1 2 3 4 5 ... 20
收藏数 220,463
精华内容 88,185
关键字:

动画