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>