仿荷包動畫

實現功能:實現簡單動畫,標題欄圖標隨着窗口一起位移放大


前言:由於動畫比較簡單,但計算過程比較瑣碎,就不一一講解,說一下思路跟步驟,再提一下比較麻煩處理的地方。

實現步驟: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謝謝,主要做電影解說這一塊,每個程序員都想跳出寫代碼的坑,希望多多支持



發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章