仿荷包动画

实现功能:实现简单动画,标题栏图标随着窗口一起位移放大


前言:由于动画比较简单,但计算过程比较琐碎,就不一一讲解,说一下思路跟步骤,再提一下比较麻烦处理的地方。

实现步骤:1.不管是图标位移还是窗口位移。都有三个动作,一个是move(),移动过程,一个手指稍微移动后释放窗口自动弹回去的的动作up(),还有自动弹开的动作down(),窗口跟图标的位移区别是窗口的位移距离是图标的两倍,还有需要处理临界值的问题,所以我封装了以下方法:

public void animIconMove(float desY)   //图标要移动的目的位置,因为在移动的过程中,其实是每次位移一下点一小点,然后从视觉上看起来是慢慢移动的效果。

public void animIconDown(long time)   //图标移动到目的地终点的位置,传进来一个时间是位移的时间。

public void animIconUp()//图标移动到起点位置,忘了传时间,项目太赶时间写死了。。

对应背景层的几个方法:

private void animBgMove(float destTouchY)

public void animBgDown(long time)

public void animBgUp()

2.down跟up方法没什么好说的,直接一个位移动画,传坐标跟时间就好。

举个例子,背景层下移的动画,控件 llContent(移动窗体的父窗体),y(需要改变的属性),tvBgCurrentY(背景层当前的位置),llRedHeight+llTitleHeight(红色广告快+标题栏高度)

AnimatorSet animatorSet = new AnimatorSet();
		ObjectAnimator one = ObjectAnimator.ofFloat(llContent, "y",tvBgCurrentY,llRedHeight+llTitleHeight);
		animatorSet.play(one);
		animatorSet.setDuration(time);
		animatorSet.start();

重点看一下图标的移动,animIconMove(),因为他需要考虑几个临界情况比较麻烦。因为图标涉及到一个放大跟缩小,放大跟缩小动画可以通过属性动画改变scaleX跟scaleY来实现并不麻烦,麻烦的是缩放的比例怎么算?我是根据位移来计算的,有个位移公式,将位移转换为缩放的比例系数scale,然后在原有的scale基础上相加,就实现了缩放,但是,这个位移有个不太好计算的地方,比如我们从A移动到B,假设A是你当前的位置,B是你想要移动的目的地终点的位置,但当AB的距离很短的时候,你手指去移动,可能是会有偏差度,可能这个距离已经超过了AB的长度,所以就需要考虑临界值的情况,比如你手指移动的距离是C,那么你真正要得到位移的距离AB,应该是需要减去多余的距离,因为我们在位移的过程中还带有缩放,如果不考虑这临界情况,当你的手指快速在临界位置移动时候,就会出现动画变形了。


3.讲完了动画,还有一个比较棘手的问题,就是事件冲突,这个对不了解事件传递的人,估计是看不懂的 ,所以请先去了解完事件传递之后,再接着往下看。

情况一:发现当我们窗口动画关上的时候,也就是这种情况,当你点击屏幕上的区域,会有一种情况发生,就是事件穿透,在这块区域背后的按钮响应了,这种情况是当你父窗体拿到事件之后,由于事件是从父窗体层层传递到内部子控件的,所以响应了事件。我的做法是重写父窗体的LinearLayout,在里面重写onInterceptTouchEvent,这个方法简单介绍一下,当前容器拿到事件之后,他会判断一下是否往下传递,所以,配合我们的项目的业务逻辑,但窗体关闭的时候,我们就需要将这个事件拦截,不让他传递到子控件按钮上去。所以我给这个LinearLayout添加了个字段private boolean ifInterceptTouchEvent;然后在代码中对应逻辑代码出写上llRedBg.setInterceptState(false/true);设置是否拦截。


好不容易解决了一个事件,还有另外一个事件冲突。

情况二:还是上图。我们上图中有个“点击申请额度”大按钮,由于我们的动画是对整个窗体添加的事件,所以窗体最先在外层拿到事件后,继续层层传递,发现里面有个点击事件去消费。所以导致一种情况,你滑动点击申请额度那个按钮,窗口是没办法移动的。但你移动按钮以外的区域 ,窗口是正常的。这就有点蛋疼了,因为按钮那么大一块。你不让它移动,体验很不好。这里我的想法是,父窗体拿到事件之后,当传递到子控件button,先根据业务决定当前状态能否点击。如果不能的话,再将事件传递回去给父窗体,让父窗体去移动,这里要注意的是,如果你没有传递回去,又会导致窗体没有移动的情况,所以需要多加小心。这里还有另一种解决方法,简单粗暴,直接对按钮添加触摸监听,然后把对最外层窗体添加的触摸事件的代码copy一份过来,就搞定了。

4.再补充一点,刚才忘了,由于我们最开始对窗体的移动时候,都是用单指的情况,如果多只手指,又画导致动画变形,什么原因呢?由于你两只手指触碰,就会有两个触点,两个触点,就会导致,你的图标在移动的时候,他不知道哪个才是你想要的目的地,所以这里需要特殊处理下,在窗体的onTouch事件里面,除了原来的:move,down,up,还要添加ACTION_POINTER_1_UP,ACTION_POINTER_2_DOWN。

ACTION_POINTER_1_UP:当第一只手指释放之后(要注意一下,当你只有一只手指时候,这方法是不会移动的,因为你只有一只手指,哪有所谓的触点一跟触点二啊,对吧。所以 只有当两只手指按上去,一只手指释放时候,才处理这情况):

	                                        if(temp!=0){
							lastY = temp;
						}
						if(tvIcon.getY()>tvIconEndY){
							animIconDown(200);
						}


ACTION_POINTER_2_DOWN:temp= event.getY(1);

5.大功告成,小小的动画,竟然也这般麻烦,只希望能给你点灵感。



打个广告,本人开始做微信公众号运营,愿意支持的就扫码关注一下,O(∩_∩)O谢谢,主要做电影解说这一块,每个程序员都想跳出写代码的坑,希望多多支持



猜你喜欢

转载自blog.csdn.net/u014369799/article/details/50448406