LZ-Says:最近的状态浑浑噩噩,很是不爽,得好好调节下自己~
前言
最近的状态个人觉得很不满意,今天通过一篇简短博文重新找回自己~
而今天,我们一起来聊聊Android转场动画。
那么,所谓的“转场动画”,究竟是个什么鬼?
简单可以理解为俩个Activity之间切换过程中的效果。
接下来,通过代码+效果图方式,让你直观了解并掌握有关转场动画小姿势~
本文目标
通过依次举例包括简要查看系统源码,让阅读本文的你,对Android中的转场动画掌握更加自如~
车已启动,一起来~
一、overridePendingTransition回顾
首先,我们回顾下,我们之前是如何设置Activity切换过程中的动画,毫无疑问,通过overridePendingTransition,那么我们一起来看一下实现:
overridePendingTransition(int enterAnim, int exitAnim):
enterAnim: Activity进入动画;
exitAnim: Activity退出动画。
基于上面给出的关于overridePendingTransition的使用,我们只需要引用系统已经写好的文件即可达到效果,不信你往下看:
public void getOverridePendingTransition(View view) { startActivity(new Intent(selfActivity, OverridePendingTransitionActivity.class)); overridePendingTransition( android.R.anim.fade_in, android.R.anim.fade_out); }
这里需要注意:
这个overridePendingTransition需要放置在startActivity或者finish之后。
二、通过Style设置切换动画
此种方式比较nice,首先,需要创建values-v21目录,其次,在此目录下设置android:windowAnimationStyle,最后设置给要使用的Activity即可。
除此之外,我们还需要编写我们的anim文件,如上图,右进右出,如下:
slide_in_right: 设置从屏幕右侧进入
<?xml version="1.0" encoding="utf-8"?><set xmlns:android="http://schemas.android.com/apk/res/android"> <translate android:duration="@android:integer/config_mediumAnimTime" android:fromXDelta="100%p" android:toXDelta="0" /></set>
slide_out_right:设置从屏幕右侧出去
<?xml version="1.0" encoding="utf-8"?><set xmlns:android="http://schemas.android.com/apk/res/android"> <translate android:duration="@android:integer/config_mediumAnimTime" android:fromXDelta="0" android:toXDelta="-50%p" /></set>
其次,这里需要为大家简述下关于Style里面我们有用的几个小属性:
activityOpenEnterAnimation: 设置打开新的Activity并进入新的Activity展示的动画;
activityOpenExitAnimation: 设置打开新的Activity并销毁之前的Activity展示的动画;
activityCloseEnterAnimation: 设置关闭当前Activity进入上一个Activity展示的动画;
activityCloseExitAnimation: 设置关闭当前Activity时展示的动画
<style name="styleActivity" parent="AppTheme"> <item name="android:windowAnimationStyle">@style/activityStyleAnim</item> </style> <style name="activityStyleAnim"> <item name="android:activityOpenEnterAnimation">@anim/slide_in_right</item> <item name="android:activityOpenExitAnimation">@anim/slide_out_right</item> </style>
为你的Activity设置可通过主题去引用即可:
<activity android:name=".activity.StyleActivity" android:theme="@style/styleActivity" />
三、通过ActivityOptions/ActivityOptionsCompat共享元素实现
ActivityOptions,谷歌提供给我们在Activity切换时的转场动画类,缺陷是仅支持Api 21以上,也就是Android 5.0以上。
So,针对如上的限制,谷歌推出兼容包ActivityOptionsCompat,这个包的主要作用就是为我们省去了对当前系统版本的判断。系统源码如下:
@RequiresApi(16) private static ActivityOptionsCompat createImpl(ActivityOptions options) { if (Build.VERSION.SDK_INT >= 24) { return new ActivityOptionsCompatApi24Impl(options); } else if (Build.VERSION.SDK_INT >= 23) { return new ActivityOptionsCompatApi23Impl(options); } else { return new ActivityOptionsCompatApi16Impl(options); } }
接着,我们来看下关键方法参数所代表的含义:
makeSceneTransitionAnimation(Activity activity,View sharedElement, String sharedElementName):设置单个共享元素
Activity activity: 当前Activity;
View sharedElement: 设置共享元素的View;
String sharedElementName: 设置共享元素的名称;
既然有设置单个共享元素,那相对应的也有设置多个共享元素:
makeSceneTransitionAnimation(Activity activity,Pair《View, String>... sharedElements):设置多个共享元素
Activity activity: 当前Activity;
Pair《View, String>... sharedElements: 要设置共享元素的View;
要使用转场动画,首先需要做的就是告诉Activity支持(允许)使用转场动画,那么如何通知呢?俩种方式,如下:
方式一:代码设置
getWindow().requestFeature(Window.FEATURE_CONTENT_TRANSITIONS);
方式二:style设置
<item name="android:windowContentTransitions">true</item>
这里LZ再次对使用转场动画需要注意点叙述一次,以便加深记忆:
首先,需要设置Activity允许使用转场动画;
其次,切换的俩个Activity中的共享元素View都需要设置android:transitionName,且设置的name要一样
实现步骤如下:
设置当前Activity允许转场动画;
布局中设置transitionName,记得切换的俩个Activity的transitionName需要设置为一致;
通过ActivityOptionsCompat兼容包设置转场动画。
关键代码如下:
设置允许转场
@Override protected void onCreate(Bundle savedInstanceState) { // 设置允许使用转场动画 此属性同样可以在style设置 // <item name="android:windowContentTransitions">true</item> getWindow().requestFeature(Window.FEATURE_CONTENT_TRANSITIONS); super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); }
设置transitionName
MainActivity-Layout:
<Button android:id="@+id/btn" android:layout_width="match_parent" android:layout_height="wrap_content" android:onClick="getActivityOptions" android:text="使用ActivityOptions跳转Activity动画" android:textAllCaps="false" android:transitionName="activityOption" />
OptionActivity-Layout:
<ImageView android:layout_width="match_parent" android:layout_height="match_parent" android:background="@drawable/img1" android:scaleType="fitXY" android:transitionName="activityOption" />
跳转下一页时,绑定共享元素:
public void getActivityOptions(View view) { Button btn = findViewById(R.id.btn); ActivityOptionsCompat optionsCompat = ActivityOptionsCompat .makeSceneTransitionAnimation( this, // 当前Activity btn, // 共享元素View "activityOption"); // 共享元素名称 Intent intent = new Intent(selfActivity, ActivityOptionsCompatActivity.class); startActivity(intent, optionsCompat.toBundle()); }
掌握了设置单个共享元素,多个相对来说也是很是Easy。下面一句话概括了。
设置多个共享元素,唯一不变的是需要指定transitionName,一一对应。 其次,通过实例化Pair对象去添加共享元素or直接通过Pair去创建而添加共享元素即可。
关键代码如下:
public void getActivityOptionsMore(View view) { Button btn = findViewById(R.id.btn1); ImageView iv = findViewById(R.id.img1); ActivityOptionsCompat optionsCompat = ActivityOptionsCompat .makeSceneTransitionAnimation( this, Pair.create((View) btn, "btn1"), new Pair<View, String>(iv, "img1") ); Intent intent = new Intent(selfActivity, ActivityOptionsMoreActivity.class); startActivity(intent, optionsCompat.toBundle()); }
当LZ点击返回的时候,同样也是以转场动画效果回归,那么它究竟在哪儿实现了呢?
当用户按下返回键时,执行下面方法:
@Override public void onBackPressed() { super.onBackPressed(); }
接着瞧内部:
public void onBackPressed() { if (mActionBar != null && mActionBar.collapseActionView()) { return; } FragmentManager fragmentManager = mFragments.getFragmentManager(); if (fragmentManager.isStateSaved() || !fragmentManager.popBackStackImmediate()) { finishAfterTransition(); // 过渡之后finish } }
/** * Reverses the Activity Scene entry Transition and triggers the calling Activity * to reverse its exit Transition. When the exit Transition completes, * {@link #finish()} is called. If no entry Transition was used, finish() is called * immediately and the Activity exit Transition is run. * @see android.app.ActivityOptions#makeSceneTransitionAnimation(Activity, android.util.Pair[]) */ public void finishAfterTransition() { if (!mActivityTransitionState.startExitBackTransition(this)) { finish(); } }
以下三点,乃是谷歌为我们提供好的,直接拿过来使用就OK~
四、滑动(Slide)使用
public void getActivityOptionSlide(View view) { Slide slide = new Slide(); slide.setDuration(800); getWindow().setExitTransition(slide); getWindow().setEnterTransition(slide); ActivityOptionsCompat optionsCompat = ActivityOptionsCompat.makeSceneTransitionAnimation(selfActivity); Intent intent = new Intent(selfActivity, ActivityOptionsCompatActivity.class); startActivity(intent, optionsCompat.toBundle()); }
五、展开(Explode)使用
public void getActivityOptionsExplode(View view) { Explode explode = new Explode(); explode.setDuration(800); getWindow().setExitTransition(explode); getWindow().setEnterTransition(explode); ActivityOptionsCompat optionsCompat = ActivityOptionsCompat.makeSceneTransitionAnimation(selfActivity); Intent intent = new Intent(selfActivity, ActivityOptionsCompatActivity.class); startActivity(intent, optionsCompat.toBundle()); }
六、渐变(Fade)使用
public void getActivityOptionsFade(View view) { Fade fade = new Fade(); fade.setDuration(800); getWindow().setExitTransition(fade); getWindow().setEnterTransition(fade); ActivityOptionsCompat optionsCompat = ActivityOptionsCompat.makeSceneTransitionAnimation(selfActivity); Intent intent = new Intent(selfActivity, ActivityOptionsCompatActivity.class); startActivity(intent, optionsCompat.toBundle()); }