Android開發之Activity轉場動畫

yungfan發表於2016-04-18

引子

相信開發過iOS的程式設計師都知道iOS ViewController之間的跳轉動畫非常多,很酷對不對?這讓開發Android的羨慕不已,曾幾何時,Android中的Activity跳轉是何等的生硬,But,在Android 5.0以後,Google也為Activity的轉場設計了更加友好的動畫效果。

轉場動畫(Activity Transition)基本介紹

Android 5.0 提供了三種Transition型別 進入:決定Activity中的所有的檢視怎麼進入螢幕。 退出:決定一個Activity中的所有檢視怎麼退出螢幕。 共享元素:決定兩個activities之間的過渡,怎麼共享(它們)的檢視。

進入和退出包含如下動畫效果

  • explode(分解) – 從螢幕中間進或出
  • slide(滑動) - 從螢幕邊緣進或出地
  • fade(淡出) –通過改變螢幕上檢視的不透明度達到新增或者移除檢視的效果

共享元素包含如下動畫效果

  • changeBounds - 改變目標檢視的佈局邊界
  • changeClipBounds - 裁剪目標檢視邊界
  • changeTransform - 改變目標檢視的縮放比例和旋轉角度
  • changeImageTransform - 改變目標圖片的大小和縮放比例

實踐

1.準備好2個Activity的佈局,弄幾個按鈕,分別對應幾種轉場動畫。

activity_one.xml —— ActivityOne的佈局,其中最後一個Button是為了做共享元素動畫

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="#ff0000"
    android:gravity="center"
    android:orientation="vertical"
    tools:context=".MainActivity">

    <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center_horizontal"
        android:onClick="explode"
        android:text="explode" />

    <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center_horizontal"
        android:onClick="slide"
        android:text="slide" />

    <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center_horizontal"
        android:onClick="fade"
        android:text="fade" />

    <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center_horizontal"
        android:onClick="share"
        android:text="share" />


    <Button
        android:id="@+id/share"
        android:layout_width="40dp"
        android:layout_height="40dp"
        android:layout_gravity="center_horizontal"
        android:background="@drawable/football" />
</LinearLayout>

複製程式碼

activity_two.xml —— ActivityTwo的佈局,裡面的Button與第一個佈局中的最後一個Button呼應,只是大小不一樣

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="#0000ff"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    tools:context=".MainActivity">

    <Button
        android:id="@+id/share"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:transitionName="shareTransition"
        android:layout_gravity="center_horizontal"
        android:background="@drawable/football"
        android:layout_centerInParent="true"
        android:onClick="share" />
</RelativeLayout>
複製程式碼

2.ActivityOne 與 ActivityTwo

ActivityOne.java

public class ActivityOne extends Activity {


    private Intent intent;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_one);
        intent = new Intent(ActivityOne.this, ActivityTwo.class);
    }

    public void explode(View view) {

        intent.putExtra("transition", "explode");
        //將原先的跳轉改成如下方式
        startActivity(intent, ActivityOptions.makeSceneTransitionAnimation(ActivityOne.this).toBundle());

    }

    public void slide(View view) {

        intent.putExtra("transition", "slide");
        //將原先的跳轉改成如下方式
        startActivity(intent, ActivityOptions.makeSceneTransitionAnimation(ActivityOne.this).toBundle());

    }

    public void fade(View view) {

        intent.putExtra("transition", "fade");
        //將原先的跳轉改成如下方式
        startActivity(intent, ActivityOptions.makeSceneTransitionAnimation(ActivityOne.this).toBundle());

    }

    public void share(View view) {

        //共享元素
        Button share = (Button) findViewById(R.id.share);
        intent.putExtra("transition", "share");

        //將原先的跳轉改成如下方式,注意這裡面的第三個引數決定了ActivityTwo 佈局中的android:transitionName的值,它們要保持一致
        startActivity(intent, ActivityOptions.makeSceneTransitionAnimation(ActivityOne.this, share, "shareTransition").toBundle());

    }


}

複製程式碼

ActivityTwo.java

public class ActivityTwo extends Activity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        // 允許使用transitions
        getWindow().requestFeature(Window.FEATURE_CONTENT_TRANSITIONS);

        String transition = getIntent().getStringExtra("transition");

        switch (transition) {
            case "explode":
                // 設定進入時進入動畫
                Explode explode = new Explode();
                explode.setDuration(1000);
                getWindow().setEnterTransition(explode);

                break;

            case "slide":
                Slide slide = new Slide();
                slide.setDuration(1000);
                getWindow().setEnterTransition(slide);

                break;

            case "fade":
                Fade fade = new Fade();
                fade.setDuration(1000);
                getWindow().setEnterTransition(fade);

                break;

            case "share":
                break;
        }

        // 所有操作在設定內容檢視之前
        setContentView(R.layout.activity_two);

    }

}
複製程式碼

說明: getWindow().setEnterTransition()是進入動畫,與之對應的getWindow().setExitTransition()就是退出轉場動畫,用法和上面一樣,就不重複了

3.測試效果

explode

explode.gif
slide

slide.gif

fade

fade.gif
share

share.gif

問題

explode效果感覺並沒有從中間進,而是從上面下來的,這是為什麼呢?歡迎知道的告知,感謝。

相關文章