使用Android.Transition框架建立動畫(1)

chris發表於2014-03-13

在Android 4.4(KitKat)中,谷歌新增了很多不錯的東西。現在我們來看看android.transition框架。

多年來,android不斷改進現有的動畫工具供開發者使用。在HoneyComb版本中,提供了很多不錯的API用於建立豐富、複雜的動畫。在此基礎上,KitKat的android.transition讓我們可以通過一種更直觀的方式定義動畫效果。

Scene和Transition

先從Scene和Transition概念說起。Scene定義了介面的當前狀態資訊,而Transition定義了介面之間的切換。

可以從佈局檔案中載入Scene定義,示例如下:

其中container在Scene中是一個包含了所有view的ViewGroup。如果是在fragment中,Scene就是傳入onCreateView()方法的引數。使用Transition的最簡單方式就是使用TransitionManager處理,示例如下:

如果在TransitionManager中不明確需要指定哪個Transition,就會預設使用AutoTransition,這個我們會後面介紹。也可以用inflater載入現有的view來建立Scene,示例如下:

Andorid.Transition實踐

我們來看一個更詳細的示例,首先從專案主頁下載示例程式碼AndroidTransitionExample。這已經是一個已完成的專案了,所以也可以用git checkout檢出程式碼(以下是詳細解釋)。

首先新建只包含一個Fragment的專案,這樣可以更容易記錄一些資訊。我們為TransitionFragment新建一個xml佈局檔案,叫做fragment_transition_scene_1.xml。接著往裡面新增一個TextView,然後在TextView下面再新增一個Button,如下:

fragment_transition_scene_1.xml

你一定猜得到,我們接下來還要新建另一個xml佈局檔案,fragment_transition_scene_2.xml。它和上一個佈局檔案基本一樣,只是把Button移到佈局底部。示例如下:

這是兩個佈局的螢幕截圖:

transition_01

transition_02

為了看Transition的效果,我們從第二個佈局檔案中建立Scene。點選goButton的時候展示Transition的效果。我們先修改一下TransitionFragment.onCreateView()方法的程式碼,如下:

這是點選goButton的效果:

transition_03

為什麼會產生這樣的效果呢?因為如果view有相同的ID,就會被當做是同一個view,然後也會被改變(通過改變bounds),也就是說,在Scene切換時,view的位置和大小也會改變,需要注意的是兩個佈局檔案的RelativeLayout也要有相同的ID。

使用GIT實戰

如果你對整個例子程式碼感興趣的話,也可以利用GIT檢出程式碼。從AndroidTransitionExample複製一份即可,你可以用GUI git客戶端列出專案的歷史版本,也可以定位到某個具體的提交點檢出。

當然,你也可以使用命令列。使用cd命令切換到專案資料夾,然後執行以下命令:

此時,你會得到專案的提交列表,像這樣:

以上貼出的對應於simple transition這個提交點,執行以下程式碼可以把專案設定成這個狀態:

執行 git checkout ,你可以跳到任意一個提交點上,下面的插入文字會給出指示操作。

修改佈局檔案

我們來修改一下第二個佈局檔案,首先把RelativeLayout換成LinearLayout,然後我們來介紹一個在第一個佈局檔案中沒有出現的view,最後我們重新排布一下這些view,程式碼如下:

我們目前處於“1e7c5be modified layout for scene 2”提交點,在命令列執行git checkout 1e7c5be就可以切換上去。可以看到,Transition仍然起作用,在第一個Scene裡面,不存在的view竟然出現在螢幕上,然後隨著Button和TextView的移動而逐漸消失。

我們詳細看看AutoTransition,事實證明,它只是TransitionSet的子類,只是它給自己定義了一個執行序列,分別是fading out、changing bounds、fading in。

我們注意到,在第二個Transition中,AutoTransition會改變bounds,目前我們只看到了Button和TextView改變了位置,如果我們改變view的大小會出現什麼情況呢?在Button中新增layout_weight屬性來看看效果:

現在Button在轉變的過程中既改變了位置也改變了大小。

現在切換到“added layout_weight to button”這個點,命令:git checkout 092ebe0。現在再做一些變化效果,在Scene中把Button轉變成ImageView

此時切換到“example of transitioning from Button to ImageView”這個點,命令: git checkout 6b4629c。看看從Button變成ImageView的效果:

仔細看你會發現,第一個Button首先被一張切割過的圖片替換了,然後逐漸移動到最終的位置,逐漸改變大小。

如果我們改變所有views的巢狀結構,比如在Button外面套一層LinearLayout,那麼Bounds就不會改變了。transition manager要求在Scene的佈局檔案中,同一層級的view要有和之前相同的ID:

此時切換到“example of change bounds not working when changing hierarchy”這個點,命令:git checkout 2b000b3

如果我們在第一個Scene中繼續用LinearLayout包含Button,那麼還是不行。想讓它起作用的話,可以給LinearLayout一個相同的ID。這會得到兩種不同的效果。

切換到“restore transition by adding LinearLayout with id”,命令:git checkout 34e0f8f

下一篇我們我們繼續研究怎麼控制Transition,以及如何從xml檔案中載入Transition。

相關文章