-
动画:用动画给女朋友讲解 TCP 四次分手过程
2019-10-21 07:57:56大家好,我们又见面了,做为一个业余的动画师,上次的用动画的形式讲解 TCP 三次握手过程再各大平台收到了广大读者的喜爱,说文章有趣、有货、有内容,也受到了很多读者的关注。很多读者留言说什么时候用动画讲一讲 ...
作者 | 小鹿
来源 | 公众号:小鹿动画学编程
一、写在前边
大家好,我们又见面了,做为一个业余的动画师,上次的用动画的形式讲解 TCP 三次握手过程再各大平台收到了广大读者的喜爱,说文章有趣、有货、有内容,也受到了很多读者的关注。很多读者留言说什么时候用动画讲一讲 TCP 四次挥手的过程,为了应大家的要求,今天我们就生动有趣的用动画给大家分享 TCP 四次挥手(分手)过程。
上次的三次握手动画是给面试官看的,那么今天咱们换种更加有乐趣的方式,用动画和你女(男)朋友讲解 TCP 四次分手过程,讲解完,考验一下你女(男)朋友和不和你分手呢。什么?首先你先有一个女(男)朋友,这一点小鹿早就考虑到了各大单身人士。
获取方式:
如果你没有女朋友,公众号后台回复“女朋友”,即可获取。小鹿不要脸的说,作为一个优秀的动画师,女性读者也是很多的,哈哈,公众号回复“男朋友”,小鹿会给你随机发放一个,嘿嘿,不信你试试。还等什么,把你女(男)朋友拉过来给她(他)讲吧。
二、思维导图
三、为何要进行 TCP 三次握手/四次分手?
TCP 的三次握手和四次分手和你恋爱是一模一样的,从相识到相恋到分手,然后认识另一个女孩再不管重复这个过程就是数据传输在网络中不断建立起三次握手和四次分手过程。
恋爱就恋爱吧,分手就分手吧,握手握来握去,挥手挥来挥去不嫌麻烦吗?
因为上篇文章 TCP 三次握手中的为什么要进行三次握手部分讲解的不怎么详细,小鹿课下就收集了一些资料,做了一个总结,在这里补充下。
3.1 为什么要进行三次握手?
在谢希仁著《计算机网络》第四版中讲“三次握手”的目的是“为了防止已失效的连接请求报文段突然又传送到了服务端,因而产生错误”。
举个简单易懂的例子,你在微信对一个女孩表白,这条信息由于网络问题延迟发送了。
然后此时你不耐烦了,去和微信另一个女孩表白,然后另一个女孩告诉你同意了,然后你心里很高兴,把高兴的心情分享给了女孩,女孩知道了你和她在一起很高兴,此时三次握完毕,你恋爱了。
突然,到了第二天,发给第一个女孩的信息才收到,女孩认为你要和他表白,此时你已经和另一个女孩恋爱了,然后第一个女孩给你发微信同意了你的表白,但是你不理睬,那个女孩还在苦苦等待你给她分享此时的高兴心情。现在我们发现如果没有分享高兴的心情给女孩(也就是第三次握手过程),那么那个女孩一直等待,白白浪费了心思,所谓的千年都等不了一回。
如果你是客户端,女孩是服务端,服务端收到延迟的报文,以为你要和它连接,所以会给你发送确认同意连接,但你一直不搭理它,所以服务端的资源也就这么白白浪费掉了。所以知道为什么要进行三次握手了吧。在《计算机网络》书中讲“三次握手”的目的是为了解决“网络中存在延迟的重复分组”的问题。
3.2 为什么要 TCP 四次分手?
我们知道,TCP协议是一种面向连接的、可靠的、基于字节流的运输层通信协议,而且TCP是全双工模式。
对于初学者来说,定义太枯燥、无味,其实意思就是你和你女朋友聊天是面向连接的,只有连接起来才可以通信的,可靠就是你发送的信息可以保证送达到对方,全双工意思就是你不仅可以给你女朋友发消息,而且她也可以给你发信息。
为什么非要进行 TCP 四次分手?我们接着上回说到,你现在和第二个女孩子恋爱了,突然有一天发现第一个女孩子是因为没有收到你的表白而错过了在一起的时机,那么你要和第二个女孩子分手,那过程对应在 TCP 四次分手是怎么样子的?
你要给第二个女孩子微信发消息,我们分手吧,此时第二个女孩子收到消息知道了,非常伤心,就屏蔽了你。但是,此时你还没有屏蔽她,她完全可以给你继续发消息,她给你发消息说,好吧,此时你收到了确认消息,此时是第二次分手过程。那么女孩又给你发送消息,渣男,永远不要来找我。此时你又接收到消息,看到消息之后发了一个拜拜,然后你就直接屏蔽拉黑了对方,此时女孩微信显示你删除了对方,然后就把你也拉黑删除了。那么四次分手到此为止,恭喜你,成功获得下一个女孩子。上述过程就阐述了为什么要进行 TCP 四次分手,为了能够让对方屏蔽你直至最后双方互相删除掉,然后你又可以和另一个女孩三次握手了。
四、TCP 四次分手过程
初始化状态:客户端和服务端都在连接状态,接下来开始进行四次分手断开连接操作。
- 第一次分手:第一次分手无论是客户端还是服务端都可以发起,因为 TCP 是全双工的。
假如客户端发送的数据已经发送完毕,发送FIN = 1 告诉服务端,客户端所有数据已经全发完了,服务端你可以关闭接收了,但是如果你们服务端有数据要发给客户端,客户端照样可以接收的。此时客户端处于FIN = 1等待服务端确认释放连接状态。
- 第二次分手:服务端接收到客户端的释放请求连接之后,知道客户端没有数据要发给自己了,然后服务端发送ACK = 1告诉客户端受到你发给我的信息,此时服务端处于 CLOSE_WAIT 等待关闭状态。
- 第三次分手:此时服务端向客户端把所有的数据发送完了,然后发送一个FIN = 1,用于告诉客户端,服务端的所有数据发送完毕,客户端你也可以关闭接受数据连接了。此时服务端状态处于LAT_ACK状态,来等待确认客户端是否收到了自己的请求。
- 第四次分手:此时如果客户端收到了服务端发送完的信息之后,就发送ACK = 1,告诉服务端,客户端已经收到了你的信息。但是我们发现上图中有一个 2 MSL 的延迟等待。
五、为什要有 2 MSL 等待延迟?
对应这样一种情况,最后客户端发送的ACK = 1给服务端的过程中丢失了,服务端没收到,服务端怎么认为的?我已经发送完数据了,怎么客户端没回应我?是不是中途丢失了?然后服务端再次发起断开连接的请求,一个来回就是2MSL,这里的两个来回由那一个来回组成的?
客户端给服务端发送的ACK = 1丢失,服务端等待 1MSL没收到,然后重新发送消息需要1MSL。如果再次接收到服务端的消息,则重启2MSL计时器,发送确认请求。客户端只需等待2MSL,如果没有再次收到服务端的消息,就说明服务端已经接收到自己确认消息;此时双方都关闭的连接,TCP 四次分手完毕。
六、如果双方建立连接,一方出问题怎么办?
如果双方建立连接,一方出问题怎么办?为了防止出现上述恋爱故事中千年等一回的情况,已经建立连接,但是服务端一直等待接收,发送端出现问题一直不能发送。
所以设计一个保活的计时器,如果一方出现问题,另一方过了这个计时器的时间,就发送试探报文,以后每隔 75 秒发送一次。若一连发送10个探测报文仍然没反应,服务器就认为客户端出了故障,接着就关闭连接。
七、小结
今天用动画的形式给你女(男)朋友讲了 TCP 四次分手的过程,文章的内容以及展现形式是最基础的内容。
最后小鹿为大家整理的三次握手和四次分手整张图,如下:
最后希望你和你的女朋友永远三次握手,永不四次分手。
上一篇:动画:用动画给面试官解释 TCP 三次握手过程
推荐阅读:
1、面试:你真的懂网络分层模型吗?(上)
2、面试:你真的懂网络分层模型吗?(下)
❤️ 不要忘记留下你学习的脚印 [点赞 + 收藏 + 评论]
文章都看完了,为何不妨点个赞呢?嘻嘻,那就说明你很自私,你怕那么好的文章让别人也看到。开个小小玩笑。
其实我也很自私,我把我的一直以来坚持原创的公众号:「小鹿动画学编程」偷偷给你,里边汇聚了小鹿以动画形式讲解的数据结构与算法、网络原理、Web 等技术文章。
一些后台小伙伴问我平常如何学习的,学习资料哪里获取,我就不一一回复了!一般我都是通过看一些编程书籍和开源的社区进行自学,一些学习资料和电子书也分享到下边了,有需要的自取。
编程在于永无止境的去学习,去学习前辈积累的经验,书籍就是最好的一种媒介方式,列出以下自己看过的优秀书籍,整理成了 PDF 版。
- 前端:《javascript高级程序设计》《JavaScript 权威指南》《你不知道的JavaScript(上中下卷)》等;
- java:《Effective Java》《Thinking in Java》《Java 编程思想》《java核心技术》等;
- 算法:《大话数据结构》《算法图解》《算法导论》《编程之美》《数据结构与算法:C语言描述》等;
- 其他相关计算机书籍;
搜索我的公众号:「小鹿动画学编程」后台回复关键词
- 回复「后台」,获取 java 等自学资料
- 回复「前端」,获取前端等自学资料
- 回复「电子书」获取一下书籍资料!
动一动你的小手,点赞就完事了,每个人出一份力量(点赞 + 评论)就会让更多的学习者加入进来!非常感谢! ̄ω ̄=
作者Info:
【作者】:小鹿
【原创公众号】:小鹿动画学编程。
【简介】:和小鹿同学一起用动画的方式从零基础学编程,将 Web前端领域、数据结构与算法、网络原理等通俗易懂的呈献给小伙伴。先定个小目标,原创 1000 篇的动画技术文章,和各位小伙伴共同努力一起学习!公众号回复 “资料” 送一从零自学资料大礼包!
【转载说明】:转载请说明出处,谢谢合作!~
-
Android属性动画完全解析(上),初识属性动画的基本用法
2015-04-09 09:56:15在手机上去实现一些动画效果算是件比较炫酷的事情,因此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,就可以这样写:
当然也许你并不需要小数位数的动画过渡,可能你只是希望将一个整数值从0平滑地过渡到100,那么也很简单,只需要调用ValueAnimator的ofInt()方法就可以了,如下所示:ValueAnimator anim = ValueAnimator.ofFloat(0f, 5f, 3f, 10f); anim.setDuration(5000); anim.start();
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,使用这个类就可以解决掉实现接口繁琐的问题了,如下所示:
这里我们向addListener()方法中传入这个适配器对象,由于AnimatorListenerAdapter中已经将每个接口都实现好了,所以这里不用实现任何一个方法也不会报错。那么如果我想监听动画结束这个事件,就只需要单独重写这一个方法就可以了,如下所示:anim.addListener(new 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当中就可以这样写:
而如果我们想将一个视图的alpha属性从1变成0,就可以这样写:<animator xmlns:android="http://schemas.android.com/apk/res/android" android:valueFrom="0" android:valueTo="100" android:valueType="intType"/>
其实XML编写动画在可读性方面还是挺高的,上面的内容相信不用我做解释大家也都看得懂吧。<objectAnimator xmlns:android="http://schemas.android.com/apk/res/android" android:valueFrom="1" android:valueTo="0" android:valueType="floatType" android:propertyName="alpha"/>
另外,我们也可以使用XML来完成复杂的组合动画操作,比如将一个视图先从屏幕外移动进屏幕,然后开始旋转360度,旋转的同时进行淡入淡出操作,就可以这样写:
这段XML实现的效果和我们刚才通过代码来实现的组合动画的效果是一模一样的,每个参数的含义都非常清楚,相信大家都是一看就懂,我就不再一一解释了。<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文件是编写好了,那么我们如何在代码中把文件加载进来并将动画启动呢?只需调用如下代码即可:
调用AnimatorInflater的loadAnimator来将XML动画文件加载进来,然后再调用setTarget()方法将这个动画设置到某一个对象上面,最后再调用start()方法启动动画就可以了,就是这么简单。Animator animator = AnimatorInflater.loadAnimator(context, R.animator.anim_file); animator.setTarget(view); animator.start();
好的,通过本篇文章的学习,我相信大家已经对属性动画的基本用法已经有了一个相当不错的认识,并把最常用的一些功能都掌握好了,那么本篇文章的内容就到这里,下篇文章当中会继续介绍属性动画,讲解ValueAnimator和ObjectAnimator的高级用法,感兴趣的朋友请继续阅读 Android属性动画完全解析(中),ValueAnimator和ObjectAnimator的高级用法 。
关注我的技术公众号,每天都有优质技术文章推送。关注我的娱乐公众号,工作、学习累了的时候放松一下自己。
微信扫一扫下方二维码即可关注:
-
Android 安卓动画 属性动画 - 旋转动画
2018-09-03 20:47:26属性动画的出现,弥补了补间动画的不足之处,补间动画,只是改变了表面上的东西,但是其中属性并未改变,而属性动画相反,改变了表面上的东西,并且也更改了其属性。 类:ObjectAnimator 用于操作属性动画的类 ...引入
属性动画的出现,弥补了补间动画的不足之处,补间动画,只是改变了表面上的东西,但是其中属性并未改变,而属性动画相反,改变了表面上的东西,并且也更改了其属性。
类:ObjectAnimator
用于操作属性动画的类
动画 - 相关文章篇
帧动画
帧动画: https://blog.csdn.net/qq_40881680/article/details/82222684
补间动画
补间动画-平移动画: https://blog.csdn.net/qq_40881680/article/details/82255459
补间动画-缩放动画: https://blog.csdn.net/qq_40881680/article/details/82260914
补间动画-旋转动画: https://blog.csdn.net/qq_40881680/article/details/82261557
补间动画-透明/渐变动画: https://blog.csdn.net/qq_40881680/article/details/82261869
补间动画-组合动画(四个动画一起播放): https://blog.csdn.net/qq_40881680/article/details/82285987
属性动画
属性动画-渐变透明动画: https://blog.csdn.net/qq_40881680/article/details/82318363
属性动画-旋转动画: https://blog.csdn.net/qq_40881680/article/details/82354017
属性动画-缩放动画: https://blog.csdn.net/qq_40881680/article/details/82377850
属性动画-移动动画: https://blog.csdn.net/qq_40881680/article/details/82378391
属性动画-组合动画: https://blog.csdn.net/qq_40881680/article/details/82381258
布局文件 篇
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" tools:context=".MainActivity"> <LinearLayout android:layout_width="match_parent" android:layout_height="0dp" android:layout_weight="1" android:background="#9c98ce" android:orientation="vertical" android:paddingLeft="20dp" android:paddingRight="20dp" android:paddingTop="10dp"> <Button android:id="@+id/button" android:layout_width="match_parent" android:layout_height="wrap_content" android:background="#5b7bda" android:text="点击演示动画" android:textColor="#fff" /> </LinearLayout> <LinearLayout android:layout_width="match_parent" android:layout_height="0dp" android:layout_weight="4" android:orientation="vertical"> <ImageView android:id="@+id/image" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center" android:layout_marginTop="20dp" android:background="@mipmap/kuiba" /> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center" android:text="《魁拔》" android:textSize="18sp" /> </LinearLayout> </LinearLayout>
代码逻辑 篇
属性动画用到的是:ObjectAnimator
package com.example.text.shuxingdonghua; import android.animation.ObjectAnimator; import android.os.Bundle; import android.support.v7.app.AppCompatActivity; import android.view.View; import android.widget.Button; import android.widget.ImageView; import android.widget.Toast; public class MainActivity extends AppCompatActivity implements View.OnClickListener { ObjectAnimator objectAnimator; private Button button; private ImageView image; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); initView(); } private void initView() { button = (Button) findViewById(R.id.button); image = (ImageView) findViewById(R.id.image); button.setOnClickListener(this); image.setOnClickListener(this); } @Override public void onClick(View v) { switch (v.getId()) { case R.id.button: objectAnimator = ObjectAnimator.ofFloat(image,"rotation",360f); objectAnimator.setDuration(2000); objectAnimator.start(); break; case R.id.image: Toast.makeText(this, "我是属性动画", Toast.LENGTH_SHORT).show(); break; } } }
AndroidStudio快速实例化-插件安装与使用:https://blog.csdn.net/qq_40881680/article/details/82012180
objectAnimator = ObjectAnimator.ofFloat(image,"rotation",360f);
将图片旋转360度,只有一次效果
objectAnimator = ObjectAnimator.ofFloat(image,"rotation",0f,360f);
将图片,从初始值0度,顺时针转360度
objectAnimator = ObjectAnimator.ofFloat(image,"rotation",0f,360f,0f);
将图片,从初始0度,顺时针旋转360度,再逆时针旋转360度到0度
ObjectAnimator.ofFloat()括号中的参数:
第一个参数,要实现动画的控件id
第二个参数,要实现的动画属性,以下列出6种:
propertyName
详细作用 alpha 实现渐变效果 rotation 实现旋转旋转效果 translationX 实现水平移动效果(左或右移动) translationY 实现纵向移动效果(向上或者向下移动) scaleX 实现轴X缩放效果(放大或者缩小) scaleY 实现轴Y缩放效果(放大或者缩小) 后面的参数就不多做解释了,以上都有
效果演示 篇
第一种:将图片旋转360度
第二种:将图片,从初始值0度,顺时针转360度
第三种:将图片,从初始0度,顺时针旋转360度,再逆时针旋转360度到0度
-
Android 安卓动画 属性动画 - 缩放动画
2018-09-04 09:28:24属性动画的出现,弥补了补间动画的不足之处,补间动画,只是改变了表面上的东西,但是其中属性并未改变,而属性动画相反,改变了表面上的东西,并且也更改了其属性。 类:ObjectAnimator 用于操作属性动画的类 ...引入
属性动画的出现,弥补了补间动画的不足之处,补间动画,只是改变了表面上的东西,但是其中属性并未改变,而属性动画相反,改变了表面上的东西,并且也更改了其属性。
类:ObjectAnimator
用于操作属性动画的类
动画 - 相关文章篇
帧动画
帧动画: https://blog.csdn.net/qq_40881680/article/details/82222684
补间动画
补间动画-平移动画: https://blog.csdn.net/qq_40881680/article/details/82255459
补间动画-缩放动画: https://blog.csdn.net/qq_40881680/article/details/82260914
补间动画-旋转动画: https://blog.csdn.net/qq_40881680/article/details/82261557
补间动画-透明/渐变动画: https://blog.csdn.net/qq_40881680/article/details/82261869
补间动画-组合动画(四个动画一起播放): https://blog.csdn.net/qq_40881680/article/details/82285987
属性动画
属性动画-渐变透明动画: https://blog.csdn.net/qq_40881680/article/details/82318363
属性动画-旋转动画: https://blog.csdn.net/qq_40881680/article/details/82354017
属性动画-缩放动画: https://blog.csdn.net/qq_40881680/article/details/82377850
属性动画-移动动画: https://blog.csdn.net/qq_40881680/article/details/82378391
属性动画-组合动画: https://blog.csdn.net/qq_40881680/article/details/82381258
布局文件 篇
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" tools:context=".MainActivity"> <LinearLayout android:layout_width="match_parent" android:layout_height="0dp" android:layout_weight="1" android:background="#9c98ce" android:orientation="vertical" android:paddingLeft="20dp" android:paddingRight="20dp" android:paddingTop="10dp"> <Button android:id="@+id/button" android:layout_width="match_parent" android:layout_height="wrap_content" android:background="#5b7bda" android:text="点击演示动画" android:textColor="#fff" /> </LinearLayout> <LinearLayout android:layout_width="match_parent" android:layout_height="0dp" android:layout_weight="4" android:orientation="vertical"> <ImageView android:id="@+id/image" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center" android:layout_marginTop="20dp" android:background="@mipmap/kuiba" /> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center" android:text="《魁拔》" android:textSize="18sp" /> </LinearLayout> </LinearLayout>
代码逻辑 篇
属性动画用到的是:ObjectAnimator
public class MainActivity extends AppCompatActivity implements View.OnClickListener { ObjectAnimator objectAnimator; private Button button; private ImageView image; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); initView(); } private void initView() { button = (Button) findViewById(R.id.button); image = (ImageView) findViewById(R.id.image); button.setOnClickListener(this); image.setOnClickListener(this); } @Override public void onClick(View v) { switch (v.getId()) { case R.id.button: objectAnimator = ObjectAnimator.ofFloat(image,"scaleX",2f); objectAnimator.setDuration(2000); objectAnimator.start(); break; case R.id.image: Toast.makeText(this, "我是属性动画", Toast.LENGTH_SHORT).show(); break; } } }
AndroidStudio快速实例化-插件安装与使用:https://blog.csdn.net/qq_40881680/article/details/82012180
objectAnimator = ObjectAnimator.ofFloat(image,"scaleX",2f);
沿着X轴放大两倍,效果只有一次
objectAnimator = ObjectAnimator.ofFloat(image,"scaleX",1f,2f);
沿着X轴放大两倍效果
objectAnimator = ObjectAnimator.ofFloat(image,"scaleX",1f,2f,1f);
沿着X轴放大两倍效果,然后再回到初始大小
ObjectAnimator.ofFloat()括号中的参数:
第一个参数,要实现动画的控件id
第二个参数,要实现的动画属性,以下列出6种:
propertyName
详细作用 alpha 实现渐变效果 rotation 实现旋转旋转效果 translationX 实现水平移动效果(左或右移动) translationY 实现纵向移动效果(向上或者向下移动) scaleX 实现轴X缩放效果(放大或者缩小) scaleY 实现轴Y缩放效果(放大或者缩小) 后面的参数就不多做解释了,以上都有
Y轴同理,将第二个参数改为scaleY即可
若想要实现X,Y轴同时缩放,可以参照属性 动画-组合动画
效果演示 篇
沿着X轴放大两倍,效果只有一次
沿着X轴放大两倍效果
沿着X轴放大两倍效果,然后再回到初始大小
-
Android 安卓动画 补间动画 - 缩放动画
2018-08-31 19:36:54补间动画之缩放动画 实现效果:点击按钮后实现按钮放大效果 补间动画概念:就是从一个画面过渡到另一个画面时让人看到中间动画效果! 动画 - 相关文章篇 帧动画 帧动画: ... -
HTML5浪漫爱心表白动画在线演示程序
2014-02-12 23:50:10HTML5浪漫爱心表白动画在线演示.htm 修改一下情人节送女友 -
Android动画效果集合开源APP(BaseAnimation1.3)程序源码
2014-02-10 20:31:35BaseAnimation1.3版本增加如下动画 1.Splash增加2个动画 2.高仿动画效果增加10个 3.ListView集合增加15个 4.自定义控件集合增加17个 5.页面滑动增加4个 共增加48个动画效果 下载app源码的朋友需要把 BAnim ... -
Android 安卓动画 属性动画 - 移动动画
2018-09-04 10:28:24属性动画的出现,弥补了补间动画的不足之处,补间动画,只是改变了表面上的东西,但是其中属性并未改变,而属性动画相反,改变了表面上的东西,并且也更改了其属性。 类:ObjectAnimator 用于操作属性动画的类 ... -
Android 安卓动画 属性动画 - 组合动画
2018-09-04 11:54:30属性动画的出现,弥补了补间动画的不足之处,补间动画,只是改变了表面上的东西,但是其中属性并未改变,而属性动画相反,改变了表面上的东西,并且也更改了其属性。 类:ObjectAnimator 用于操作属性动画的类 ... -
Android 安卓动画 补间动画 - 组合(四个动画) 动画
2018-09-01 12:47:32顾名思义,就是四种动画(平移动画,旋转动画,缩放动画,渐变动画)一起实现效果,四种动画有着共同的属性,也有各自的特有属性,下面列出来的四种动画的共有属性 实现目标:点击按钮后 四种动画(平移动画,旋转动画... -
Android 安卓动画 补间动画 - 旋转动画
2018-08-31 20:43:00补间动画之平移动画 实现效果:点击按钮后旋转这个按钮 补间动画概念:就是从一个画面过渡到另一个画面时让人看到中间动画效果! 动画 - 相关文章篇 帧动画 帧动画: ... -
Android 安卓动画 属性动画 - 渐变/透明度 动画
2018-09-02 20:26:05属性动画的出现,弥补了补间动画的不足之处,补间动画,只是改变了表面上的东西,但是其中属性并未改变,而属性动画相反,改变了表面上的东西,并且也更改了其属性。 类:ObjectAnimator 用于操作属性动画的类 ... -
Android基础动画,组合动画,帧动画,布局动画,Activity跳转动画
2016-11-07 18:48:02>Android中常用的动画都在这里了,包含了基本的动画【透明度动画,缩放动画,旋转动画,位移动画】;还有就是这四种动画的组合实现; 还有布局动画,就是在加载布局时的动画;还有Activity跳转的动画。 -
Android 安卓动画 补间动画 - 平移动画
2018-08-31 15:16:49补间动画之平移动画 实现效果:向右下方向移动控件 补间动画概念:就是从一个画面过渡到另一个画面时让人看到中间动画效果! 动画 - 相关文章篇 帧动画 帧动画: ... -
Android动画之视图动画和属性动画
2016-05-13 16:19:37Android 动画分为两大类,分别是视图动画(View Animation)和属性动画(Property Animation)。对于这两种动画,都能够使用xml和代码的形式定义动画。View Animation视图动画是Android最基础的动画,在API 1中就... -
Android的三种动画详解(帧动画、View动画、属性动画)
2019-06-21 22:54:03Android的动画分为了三种, 分别是 帧动画、View动画、属性动画。 1、帧动画 帧动画就是顺序播放一组预先定义好的图片,就类似于我们观看视频,就是一张一张的图片连续播放。 帧动画的使用很简单,总共就两个步骤... -
Android 安卓动画 补间动画 - 透明/渐变 动画
2018-08-31 21:02:22补间动画之 透明/渐变 动画 实现效果:点击按钮后按钮从完全透明到不透明 补间动画概念:就是从一个画面过渡到另一个画面时让人看到中间动画效果! 动画 - 相关文章篇 帧动画 帧动画: ... -
Android 动画:手把手教你使用 补间动画 (视图动画)
2017-06-01 08:21:22可是动画的种类繁多、使用复杂,每当需要 采用自定义动画 实现 复杂的动画效果时,很多开发者就显得束手无策 本文将详细介绍 Android 动画中 补间动画的原理 & 使用 学习Android 动画最好先了解:自定义View的原理,... -
Android动画
2019-11-24 19:11:58这篇博客主要总结一下自己在项目中对动画的一些使用。我写博客,其实更多的是总结自己在工作中用到的一些知识。比如某一段时间一个知识点相关的技术用的比较多,那我会总结一下。其实,对于Android动画的总结,这是... -
Shader动画之UV动画与顶点动画
2017-12-18 20:40:08用Shader实现动画主要包括两种方式:1.UV动画,2.顶点动画 -
Android开发——View动画、帧动画和属性动画详解
2016-10-02 19:28:10我们都知道Android动画分为三类:View动画、帧动画和属性动画。先对这三种动画做一个概述。View动画是一种渐进式动画,通过图像的平移、缩放、旋转和透明度等各种渐进式变换完成动画效果。帧动画是通过不停的切换... -
Android动画集合开源APP
2014-01-13 22:56:25BaseAnimation,如果有新版本会自动提醒大家更新,也希望大家多多贡献自己的动画xml文件或者其他源码,一起来打造这个开源的app 博客地址:http://blog.csdn.net/duguang77/article/details/18230867 -
Android 动画之帧动画用法详解
2020-04-21 23:24:50本文目录帧动画概念帧动画实现方法1:xml实现帧动画第一步:导入帧动画素材第二步:创建帧动画文件第三步:布局文件和Activity方法2:用Java代码实现帧动画 帧动画概念 在Android中,帧动画的本质是把一组预先准备好... -
Android 绘制动画(波浪动画/轨迹动画/PathMeasure)
2018-03-28 17:07:45Android 绘制动画(波浪动画/轨迹动画/PathMeasure) 本文由 Luzhuo 编写,转发请保留该信息. 原文: https://blog.csdn.net/rozol/article/details/79730582 绘制动画, 由Android的绘画功能 + 属性动画 组成的一... -
Android 属性动画:这是一篇很详细的 属性动画 总结&攻略
2017-06-08 09:00:28本文将详细介绍 Android 动画中 属性动画的原理 & 使用 相关文章阅读: 1. Android 动画系列 Android 动画:手把手教你使用 补间动画 Android 动画:你真的会使用插值器与估值器吗?(含详细实例教学) 2. ... -
Canvas线条动画
2020-09-03 19:23:39Canvas线条动画 简单的Canvas动画,代码只有71行,试试吧!没有谁天生就会,用这个动画,做为你的Canvas小结。 如果你觉得我的代码还算有趣,在你的学习中能有所帮助,请查看我的置顶文章,我由衷感谢! <!... -
Vue教程(动画-半场动画)
2019-07-21 23:12:06上篇文章我们介绍了过渡动画的实现,包括完整的 入场 和 离场 动画,但是在实际过程中我们有时可能仅仅需要使用半场动画,比如淘宝购物车的下单处理等。 Vue 半场动画 1.基础页面 基础页面设置。 <!... -
Android5.0Activity的转场动画、过渡动画、过场动画、跳转动画
2017-10-23 15:43:52Activity的转场动画很早就有,但是太过于单调,样式也不好看,于是Google在Android5.0之后,又推出的新的转场动画,效果还是非常炫的,今天我们一起来看一下。 Android5.0之后Activity的出入场动画总体上来说可以... -
Unity动画丨二、UGUI按钮动画、2D精灵动画
2018-03-21 01:37:39UGUI按钮动画目的:创建按钮在不同状态时的不同显示情况1、创建Button,进入2D界面2、Inspector—Button—Transition(转变、过渡)—Animation,点击Auto Generate Animation,保存按钮动画 同时创建 动画和控制器... -
Android动画之布局动画
2016-05-13 16:22:10Android动画之布局动画布局动画是针对于ViewGroup使用的,我们直接上效果,通过效果分析进行实现。首先我们分析一下效果图,总共可分为两种, - 在我们的界面初始化显示时,会垂直显示一条垂直的按钮,他们会从右边...
-
Docker从入门到精通
-
scala-intellij-bin-2020.3.20.zip
-
1050 螺旋矩阵 (25 分)
-
395. 至少有 K 个重复字符的最长子串
-
vue3从0到1-超详细
-
【正点原子】I.MX6U 出厂系统Qt交叉编译环境搭建V1.4.pdf
-
基于电商业务的全链路数据中台落地方案(全渠道、全环节、全流程)
-
大数据面试之HDFS副本机制
-
apache-jmeter-3.1.7z
-
groovy-ssh-expect-源码
-
MySQL 备份与恢复详解(高低版本 迁移;不同字符集 相互转换;表
-
快速排序与归并排序 - leetcode-912
-
各种显示器色域测试软件和计算显示器色域值软件和表格
-
MySQL 多实例安装 及配置主从复制实验环境
-
NFS 网络文件系统
-
光伏并网matlab仿真模型.zip
-
MMM 集群部署实现 MySQL 高可用和读写分离
-
占据主动!刘强东微博营销之道.pdf
-
数据研究必备:国内40个免费数据源.pdf
-
数学实验第一次作业.docx