《Android》『Fragment』- 如何設定不同 Fragment 之間切換時的共享元素與過渡動畫
《Android Developers 參考文獻》
《簡單介紹》
當我們在寫一個手機程式專案的時候,不可避免的一定會有頁面的切換,不管是 Activity 之間的切換,或者是 Fragment 之間的切換,在以前的時候,我們為了讓程式在切換頁面時更加美觀,往往會針對整個頁面加入像是淡進淡出等轉場動畫的效果,到了 Android 5.0 之後,更進一步的,我們可以針對在頁面中每個個別的 View,做出切換到另一個頁面時過渡動畫的效果。
什麼是共享元素?
所謂的共享元素,指的是當我們需要由 A 頁面切換到 B 頁面時,我們已知在 A 頁面中,有一個 View 可以跟 B 頁面的其中一個 View 做關聯(最簡單的應用就是在 A 頁面點選照片以後,在 B 頁面放大),做好關聯以後,我們即稱這兩個元素是共享元素,接著,我們便可以進一步設定當頁面從 A 切換到 B 時,這兩個 View 之間的過渡動畫。
什麼是過渡動畫?
過渡動畫即是當頁面由 A 切換到 B 時,其中的共享元素所使用的動畫。
《實作方法》
我們直接改寫上一篇文章的範例,來說明如何實作。
MainActivity 的部分,基本上跟上一篇文章一樣,因此這篇就不多做說明,在這裡我們宣告兩個 Fragment,名稱分別自訂為 Fragment1 與 Fragment2,對應的布局檔名稱分別為 fragment_01 與 fragment_02。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 |
package ... import ... import static android.transition.TransitionSet; public class Fragment1 extends Fragment { public static final String TAG = Fragment1.class.getSimpleName(); Button btnChangeFragmentTo02; @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { View rootView = inflater.inflate(R.layout.fragment_01, container, false); // Explode explode = new Explode(); 用來設定整個頁面的轉場效果 // explode.setDuration(2000); // setExitTransition(explode); // setEnterTransition(explode); // Fade fade = new Fade(); 用來設定整個頁面的轉場效果 // fade.setDuration(2000); // setExitTransition(fade); // setEnterTransition(fade); return rootView; } @Override public void onActivityCreated(Bundle savedInstanceState) { super.onActivityCreated(savedInstanceState); btnChangeFragmentTo02 = (Button) getView().findViewById(R.id.btnChangeFragmentTo02); btnChangeFragmentTo02.setText("Change to Fragment2"); btnChangeFragmentTo02.setOnClickListener(btnChangeFragment_Listener); } Button.OnClickListener btnChangeFragment_Listener = new View.OnClickListener() { @Override public void onClick(View v) { Fragment2 fragment2 = new Fragment2(); DetailsTransition detailsTransition = new DetailsTransition(); Fragment2.setSharedElementEnterTransition(detailsTransition); //切換至下一個頁面的轉場效果 // Fragment2.setSharedElementReturnTransition(detailsTransition); 按回上一頁的轉場效果 getActivity().getSupportFragmentManager().beginTransaction() //執行切換至 Fragment2 .addSharedElement( btnChangeFragmentTo02, getResources().getString(R.string.shareElement)) .replace(R.id.frameLayout, fragment2 , Fragment2.TAG) .commit(); } }; public class DetailsTransition extends TransitionSet { //定義轉場動畫 public DetailsTransition() { setOrdering(ORDERING_TOGETHER); addTransition(new ChangeBounds()). addTransition(new ChangeTransform()). addTransition(new ChangeImageTransform()); } } } |
Fragment1.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:paddingBottom="@dimen/activity_vertical_margin" android:paddingLeft="@dimen/activity_horizontal_margin" android:paddingRight="@dimen/activity_horizontal_margin" android:paddingTop="@dimen/activity_vertical_margin"> <Button android:id="@+id/btnChangeFragmentTo02" android:layout_width="wrap_content" android:layout_height="wrap_content" android:transitionName="@string/shareElement"/> </RelativeLayout> |
fragment_01.xml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 |
package ... import ... import android.transition.TransitionSet; public class Fragment2 extends Fragment { public static final String TAG = Fragment2.class.getSimpleName(); Button btnChangeFragmentTo01; @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { View rootView = inflater.inflate(R.layout.fragment_02, container, false); return rootView; } @Override public void onActivityCreated(Bundle savedInstanceState) { super.onActivityCreated(savedInstanceState); btnChangeFragmentTo01 = (Button) getView().findViewById(R.id.btnChangeFragmentTo01); btnChangeFragmentTo01.setText("Change to Fragment1"); btnChangeFragmentTo01.setOnClickListener(btnChangeFragment_Listener); } Button.OnClickListener btnChangeFragment_Listener = new View.OnClickListener() { @Override public void onClick(View v) { // ((MainActivity)getActivity()).gotoScene(MainActivity.SCENE_NORMAL, MainActivity.FRAG_01); Fragment1 fragment1 = new Fragment1(); DetailsTransition detailsTransition = new DetailsTransition(); viewFragment1.setSharedElementEnterTransition(detailsTransition); viewFragment1.setSharedElementReturnTransition(detailsTransition); getActivity().getSupportFragmentManager().beginTransaction() .addSharedElement( btnChangeFragmentTo01, getResources().getString(R.string.shareElement)) .replace(R.id.frameLayout, viewFragment1 , ViewFragment1.TAG) .commit(); } }; public class DetailsTransition extends TransitionSet { public DetailsTransition() { setOrdering(ORDERING_TOGETHER); addTransition(new ChangeBounds()). addTransition(new ChangeTransform()). addTransition(new ChangeImageTransform()); } } } |
Fragment2.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:paddingBottom="@dimen/activity_vertical_margin" android:paddingLeft="@dimen/activity_horizontal_margin" android:paddingRight="@dimen/activity_horizontal_margin" android:paddingTop="@dimen/activity_vertical_margin" android:gravity="bottom"> <Button android:id="@+id/btnChangeFragmentTo01" android:layout_width="wrap_content" android:layout_height="wrap_content" android:transitionName="@string/shareElement"/> </LinearLayout> |
fragment_02.xml
在這兩個 Fragment 中,我們皆宣告了一個按鈕,當按下按鈕的時候,會切換到另一個 Fragment,這邊我們將兩個 Fragment 的布局檔中的 Button 介面元件定義成共享元素,定義的方式很簡單,只要在兩個頁面的布局檔中,為 Button 元件加入 android:transitionName 的屬性就行了,該屬性必須塞入一個 String 的相同唯一值,程式便可以藉此辨識此兩個 Button 為共享元素。
在定義好共享元素以後,接著我們必須進一步設定此共享元素的轉場動畫,透過繼承 TransitionSet 的方式,我們自訂了一個名為 DetailsTransition 的轉場動畫類別,並在裡面定義了基本的動畫屬性。
現在我們已經定義好共享元素以及其所要使用的轉場動畫了,只要再將這兩個資訊設定給切換 Fragment 的方法,就大功告成!設定的方式很簡單,轉場動畫的部分,直接將 Fragment 中的 setSharedElementEnterTransition(TransitionSet) 方法的參數代入定義好的轉場動畫類別即可;至於共享元素的部分,則在切換 Fragment 的時候,透過 .addSharedElement(View, transitionName) 設定即可。
臉書留言
一般留言