在Fragment进入的过程中使用动画遇到的问题
由于最近在做fragment,在应付设计师小哥哥繁杂的动画设计(没错,充满怨恨)的同时,出现一个动画不随fragment取消的问题,我把fragment设置成点击activity界面就add fragment,再次点击就remove fragment。而出现的问题就是你刚把fragment点出来,再点击把fragment remove,但是动画没有停下(即使现在fragment看不到),并且如果此时你再次点出fragment,就会发现动画执行两次甚至以上。三种动画,补间动画、ObjectAnimator、ValueAnimator都出现了这些问题。真的是惹的我很生气,解决了好久好久最后还是屈服了,不给点击remove fragment。由于很治标不治本,所以想出了以下几种解决方案:
1、利用fragment的状态判断函数,isAdded(),isDetached(),isRemoving()。
很多人包括我都觉得这些用if判断明明只是一瞬间的事情,代码执行到的时候没有就没有,它可不会等你。难道你要用个自旋锁?这里也求助一下,有没有什么办法一直监听着fragment的这几个函数。
但还是被我想到了一个地方:在用ValueAnimation的时候,因为ValueAnimation在做动画的时候每次都是经过addUpdateListener的onAnimationUpdate方法,这样每次它计算属性的时候都判断一次,这总能踩中一次。也就有点写在while循环里的意思了。
2、动画开启都用handler,在fragment remove的生命周期里把handler的消息清除。
但是动画都开始了,消息队列本来就空了,你还清什么?除非是延迟的动画任务。
3、把动画做成全局的,这样就可以在fragment的生命周期中停止。
这也是最普通最通用的方法了。平时使用动画都是随用随new,没办法在fragment的onPause和之后的生命周期函数中调用cancel方法。那只好声明为全局的。感觉这个还是适用于整套动画方案需要数量较少的几次动画,可能就需要一两个,那确实没必要搞这么多事情。如果你家设计师小哥哥跟我家的一样,那恐怕……
4、自定义动画类,实现lifecycle接口。
即使上面的方案奏效,但涉及到属性动画的话,如果是执行到一半,控件的属性已经更改,那下一次再运行的时候就会继续上一次的位置,这样还是不对,还得去把属性还原。那继承animation是最好的选择了。
这个lifecycle是Android官方的一个架构组件,可以监听activity/fragment的生命周期,这套组件原本是用来解决Android的MVC模式中activity任务过重的问题,但是这个生命监听确实挺棒的,至少我不用每次都要想着在activity的onStop或是onDestroy函数里cancel各种各样的东西。
(1)最方便的就是用适配器模式中的对象适配,然后每次调用的时候辛苦一下多加一句:getAnimation()。但是这只能简单的保证在activity/fragment stop/destroy的时候cancel动画,还不能在cancel的同时还原控件的属性。
废话不多说,直接上示例:
下图是改装后的动画类,还说的这么高端,适配器模式的对象适配,没啥特别就是拿个animation做数据成员然后用就行了,很没技术含量的类。
下图是写在activity或者fragment里的,构造函数被我写复杂了,直接传个animation对象就好。但是getLifecycle().addObserver(bganimatior);这句必须要的哦,不然它就监听不到activity/fragment的生命周期了。
(2)另一种方法就是适配器模式中的类适配。对象适配只是单纯的拿了一个animator对象,用起来还是很牵强的,一点逼格都没有。一般来说应该是直接继承animation或者animator类,这样就可以跟用普通的动画类应该用,不用麻烦的getAnimator()这么间接。
然而,这好像要重写好多好多的函数???
所以目前我还没有时间去考虑这个事情,这部分就等有缘的时候再回来啦。
//图没复制上来,下周回公司再补