1. 程式人生 > >Android動畫:轉場動畫(過度動畫) ActivityOptionsCompat

Android動畫:轉場動畫(過度動畫) ActivityOptionsCompat

ActivityOptionsCompat

簡介

Actiivty轉場動畫可以使用overridePendingTransition (int enterAnim, int exitAnim),但這種方式太老了,接下來介紹另一種方式ActivityOptions,和相容類(V4)ActivityOptionsCompat

總效果圖

這裡寫圖片描述

4個靜態方法

這裡寫圖片描述

makeCustomAnimation(Context context, int enterResId, int exitResId)
makeScaleUpAnimation(View source, int startX, int
startY, int startWidth, int startHeight) makeSceneTransitionAnimation(Activity activity, View sharedElement, String sharedElementName) makeThumbnailScaleUpAnimation(View source, Bitmap thumbnail, int startX, int startY) makeSceneTransitionAnimation(Activity activity, Pair...<View, String> sharedElements)

1 makeCustomAnimation(…)

效果圖

這裡寫圖片描述

Demo

View是Button

ActivityOptionsCompat options = ActivityOptionsCompat.makeCustomAnimation(context, android.R.anim.slide_in_left, android.R.anim.slide_out_right);
ActivityCompat.startActivity(context, new Intent(context, Activity_I.class), options.toBundle
());

2 makeScaleUpAnimation(…)

效果圖

這裡寫圖片描述

Demo

View是Button

ActivityOptionsCompat options2 = ActivityOptionsCompat.makeScaleUpAnimation(view, view.getWidth() / 2, view.getHeight() / 2, 1000, 1000);
ActivityCompat.startActivity(context, new Intent(context, Activity_I.class), options2.toBundle());

3 makeThumbnailScaleUpAnimation(…)

效果圖

這裡寫圖片描述

Demo

View是Button

ActivityOptionsCompat options3 = ActivityOptionsCompat.makeThumbnailScaleUpAnimation(view, BitmapFactory.decodeResource(getResources(), R.mipmap.b), 0, 0);
ActivityCompat.startActivity(context, new Intent(context, Activity_I.class), options3.toBundle());

4 makeClipRevealAnimation(…)

效果圖

這裡寫圖片描述

Demo

View是Button

ActivityOptionsCompat options4 = ActivityOptionsCompat.makeClipRevealAnimation(view, view.getWidth() / 2, view.getHeight() / 2, 1000, 1000);
ActivityCompat.startActivity(context, new Intent(context, Activity_I.class), options4.toBundle());

transitionName

效果圖

這裡寫圖片描述

Demo

View是Button

ActivityOptionsCompat options5 = ActivityOptionsCompat.makeSceneTransitionAnimation(MainActivity.this, iv, "options5");
ActivityCompat.startActivity(context, new Intent(context, Activity_A.class), options5.toBundle());

//多個view
ActivityOptionsCompat activityOptions = ActivityOptionsCompat.makeSceneTransitionAnimation(this, new Pair<View, String>(iv1, "iv1"), new Pair<View, String>(iv2), "iv2");

在Actiivty_A中設定transitionName

@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_a);
    context = this;

    iv_a = (ImageView) findViewById(R.id.iv_a);
    //也可以在xml中配置
//        ViewCompat.setTransitionName(iv_a,"options5");
}

XML中設定transitionName

<ImageView
    android:id="@+id/iv_a"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:transitionName="options5"
    android:src="@mipmap/b"/>

6 makeSceneTransitionAnimation(…) Transition

注意:

API>=21

//退出時使用
getWindow().setExitTransition(explode);
//第一次進入時使用
getWindow().setEnterTransition(explode);
//再次進入時使用
getWindow().setReenterTransition(explode);

當然,你也可以在style中配置

當前頁是A,點選A頁面的Button,開啟B,在按back鍵,回到A.整個過程中,windowEnterTransition是B要執行的動畫,windowExitTransition是A要退出的頁面的動畫。按back鍵,B退出是有退出動畫的,不需要在設定。

<item name="android:windowEnterTransition">@android:transition/slide_left</item>
<item name="android:windowExitTransition">@android:transition/slide_right</item>

注意:是windowEnterTransition,不是windowEnterAnimation

<item name="android:windowEnterAnimation">@android:anim/slide_in_left</item>
<item name="android:windowExitAnimation">@android:anim/slide_out_right</item>

多個view的都需要這樣的效果

ActivityOptionsCompat activityOptions = ActivityOptionsCompat.makeSceneTransitionAnimation(
        this,
        new Pair<View, String>(view.findViewById(R.id.imageview_item),
                DetailActivity.VIEW_NAME_HEADER_IMAGE),
        new Pair<View, String>(view.findViewById(R.id.textview_name),
                DetailActivity.VIEW_NAME_HEADER_TITLE));
ViewCompat.setTransitionName(mHeaderImageView, VIEW_NAME_HEADER_IMAGE);
ViewCompat.setTransitionName(mHeaderTitle, VIEW_NAME_HEADER_TITLE);

6-1 explode

效果圖

這裡寫圖片描述

Demo

View是Button

ActivityOptionsCompat options6 = ActivityOptionsCompat.makeSceneTransitionAnimation(MainActivity.this);
ActivityCompat.startActivity(context, new Intent(context, Activity_B.class), options6.toBundle());

需要在被開啟的activity中設定

@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    // 設定contentFeature,可使用切換動畫
    // getWindow().requestFeature(Window.FEATURE_CONTENT_TRANSITIONS);  或者
    requestWindowFeature(Window.FEATURE_CONTENT_TRANSITIONS);
    Transition explode = TransitionInflater.from(this).inflateTransition(android.R.transition.explode);
    getWindow().setEnterTransition(explode);

    setContentView(R.layout.activity_b);
}

可以給transition新增監聽

explode.addListener(transitionListener);

private Transition.TransitionListener transitionListener = new Transition.TransitionListener() {
   @Override
    public void onTransitionStart(Transition transition) {

    }

    @Override
    public void onTransitionEnd(Transition transition) {
        loginApp();
    }

    @Override
    public void onTransitionCancel(Transition transition) {

    }

    @Override
    public void onTransitionPause(Transition transition) {

    }

    @Override
    public void onTransitionResume(Transition transition) {

    }
};

6-2 fade

效果圖

這裡寫圖片描述

demo

View是Button

ActivityOptionsCompat options6 = ActivityOptionsCompat.makeSceneTransitionAnimation(MainActivity.this);
ActivityCompat.startActivity(context, new Intent(context, Activity_C.class), options6.toBundle());

需要在被開啟的activity中設定

@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    getWindow().requestFeature(Window.FEATURE_CONTENT_TRANSITIONS);
    Transition fade = TransitionInflater.from(this).inflateTransition(android.R.transition.fade);
    getWindow().setEnterTransition(fade);

    setContentView(R.layout.activity_b);
}

6-3 move

效果圖

這裡寫圖片描述

Demo

View是Button

ActivityOptionsCompat options6 = ActivityOptionsCompat.makeSceneTransitionAnimation(MainActivity.this);
ActivityCompat.startActivity(context, new Intent(context, Activity_D.class), options6.toBundle());

需要在被開啟的activity中設定

@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    getWindow().requestFeature(Window.FEATURE_CONTENT_TRANSITIONS);
    Transition move = TransitionInflater.from(this).inflateTransition(android.R.transition.move);
    getWindow().setEnterTransition(move);

    setContentView(R.layout.activity_b);
}

6-4 slide_bottom

效果圖

這裡寫圖片描述

Demo

View是Button

ActivityOptionsCompat options6 = ActivityOptionsCompat.makeSceneTransitionAnimation(MainActivity.this);
ActivityCompat.startActivity(context, new Intent(context, Activity_E.class), options6.toBundle());

Activity_E 需要在被開啟的activity中設定

@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    getWindow().requestFeature(Window.FEATURE_CONTENT_TRANSITIONS);
    Transition slide_bottom = TransitionInflater.from(this).inflateTransition(android.R.transition.slide_bottom);
    getWindow().setEnterTransition(slide_bottom);

    setContentView(R.layout.activity_b);
}

6-5 slide_right

效果圖

這裡寫圖片描述

Demo

View是Button

ActivityOptionsCompat options10 = ActivityOptionsCompat.makeSceneTransitionAnimation(MainActivity.this);
ActivityCompat.startActivity(context, new Intent(context, Activity_F.class), options10.toBundle());

需要在被開啟的activity中設定

public class Activity_F extends AppCompatActivity {
    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        getWindow().requestFeature(Window.FEATURE_CONTENT_TRANSITIONS);
        Transition slide_right = TransitionInflater.from(this).inflateTransition(android.R.transition.slide_right);
        getWindow().setEnterTransition(slide_right);

        setContentView(R.layout.activity_b);
    }
}

6-6 slide_top

效果圖

這裡寫圖片描述

Demo

View是Button

ActivityOptionsCompat options11 = ActivityOptionsCompat.makeSceneTransitionAnimation(MainActivity.this);
ActivityCompat.startActivity(context, new Intent(context, Activity_G.class), options11.toBundle());

需要在被開啟的activity中設定

public class Activity_G extends AppCompatActivity {
    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        getWindow().requestFeature(Window.FEATURE_CONTENT_TRANSITIONS);
        Transition slide_top = TransitionInflater.from(this).inflateTransition(android.R.transition.slide_top);
        getWindow().setEnterTransition(slide_top);

        setContentView(R.layout.activity_b);
    }
}

6-7 slide_left

效果圖

這裡寫圖片描述

Demo

View是Button

ActivityOptionsCompat options12 = ActivityOptionsCompat.makeSceneTransitionAnimation(MainActivity.this);
ActivityCompat.startActivity(context, new Intent(context, Activity_H.class), options12.toBundle());

需要在被開啟的activity中設定

public class Activity_H extends AppCompatActivity {
    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        getWindow().requestFeature(Window.FEATURE_CONTENT_TRANSITIONS);
        Transition slide_left = TransitionInflater.from(this).inflateTransition(android.R.transition.slide_left);
        getWindow().setEnterTransition(slide_left);

        setContentView(R.layout.activity_b);
    }
}

其他

優雅的退出

由A進到到B,我們使用的是轉場動畫,在B頁面,如果按back鍵,B頁面的退出也是轉場動畫,但是通常Activity頂部有個Titlte,左側是返回箭頭,那麼怎麼讓B退出的時候像進入時那樣使用轉場東動畫呢?
解決方法就是在我們給箭頭icon設定點選事件,在點選中呼叫方法onBackPressed();
這裡寫圖片描述

ic_back.setNavigationOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View view) {
        onBackPressed();
    }
});

原始碼

overridePendingTransition (int enterAnim, int exitAnim)

overridePendingTransition(R.anim.bottom_to_current,R.anim.current_to_top);

當前頁向上退出

這裡寫圖片描述
current_to_top.xml

<?xml version="1.0" encoding="utf-8"?>
<translate
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:duration="500"
    android:fromYDelta="0"
    android:toYDelta="-100%">
</translate>

bottom_to_current.xml

<?xml version="1.0" encoding="utf-8"?>
<translate
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:fromYDelta="100%"
    android:duration="500"
    android:toYDelta="0">
</translate>

當前頁向下退出

這裡寫圖片描述
current_to_bottom.xml

<?xml version="1.0" encoding="utf-8"?>
<translate
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:duration="500"
    android:fromYDelta="0"
    android:toYDelta="100%">
</translate>

top_to_current.xml

<?xml version="1.0" encoding="utf-8"?>
<translate
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:duration="500"
    android:fromYDelta="-100%"
    android:toYDelta="0">
</translate>

當前頁向右退出

這裡寫圖片描述
current_to_right.xml

<?xml version="1.0" encoding="utf-8"?>
<translate xmlns:android="http://schemas.android.com/apk/res/android"
    android:fromXDelta="0"
    android:toXDelta="100%"
    android:duration="500" >
</translate>
<!-- 要使用%,這樣才有效果,反則沒有效果,500ms不起作用 -->

left_to_current.xml

<?xml version="1.0" encoding="utf-8"?>
<translate xmlns:android="http://schemas.android.com/apk/res/android"
    android:fromXDelta="-100%"
    android:toXDelta="0"
    android:duration="500" >
</translate>
<!-- 要使用%,這樣才有效果,反則沒有效果,500ms不起作用 -->

當前頁向左退出

這裡寫圖片描述
current_to_left.xml

<?xml version="1.0" encoding="utf-8"?>
<translate xmlns:android="http://schemas.android.com/apk/res/android"
    android:fromXDelta="0"
    android:toXDelta="-100%"
    android:duration="500" >
</translate>

right_to_current.xml

<?xml version="1.0" encoding="utf-8"?>
<translate xmlns:android="http://schemas.android.com/apk/res/android"
    android:fromXDelta="100%"
    android:toXDelta="0"
    android:duration="500" >
</translate>

當前頁從右邊進入,退出時回到右邊

startActivity(new Intent(getActivity(), CommonQuestionActivity.class));
overridePendingTransition(R.anim.right_to_current,R.anim.current_to_left);
@Override
public void onBackPressed() {
    super.onBackPressed();
    overridePendingTransition(R.anim.alpha_1_1,R.anim.current_to_right);
}

Activity切換時黑屏

如果我們採用這種方式那麼會導致當前頁黑屏

startActivity(new Intent(Activity_A.this,Activity_C.class));
overridePendingTransition(R.anim.right_to_current,0);

見圖:
這裡寫圖片描述
解決方法:不實用0,仍然使用動畫,將退出動畫設定透明度從1到1.
current_stay_alpha.xml

R.anim.current_stay_alpha

overridePendingTransition(R.anim.right_to_current,R.anim.current_stay_alpha);
<?xml version="1.0" encoding="utf-8"?>
<alpha xmlns:android="http://schemas.android.com/apk/res/android"
       android:duration="500"
       android:fromAlpha="1"
       android:toAlpha="1">
</alpha>

當然,不只是current_stay_alpha,只要使當前頁保持不動都可以,下面還有

R.anim.current_stay_translate

overridePendingTransition(R.anim.right_to_current,R.anim.current_stay_translate);
<?xml version="1.0" encoding="utf-8"?>
<translate xmlns:android="http://schemas.android.com/apk/res/android"
           android:fromXDelta="0"
           android:toXDelta="0"
           android:duration="500">
</translate>

current_stay_scale.xml

overridePendingTransition(R.anim.right_to_current,R.anim.current_stay_scale)
<?xml version="1.0" encoding="utf-8"?>
<scale xmlns:android="http://schemas.android.com/apk/res/android"
       android:duration="500"
       android:fromXScale="1"
       android:fromYScale="1"
       android:toXScale="1"
       android:toYScale="1">
</scale>

current_stay_rotate.xml

overridePendingTransition(R.anim.right_to_current,R.anim.current_stay_rotate)
<?xml version="1.0" encoding="utf-8"?>
<rotate xmlns:android="http://schemas.android.com/apk/res/android"
       android:duration="500">
</rotate>

原始碼