目录介绍
-
1.业务需求:Activity正反两面,沿中心X,Y轴旋转180度
- 1.0 具体业务需求
- 1.1 用3D效果做翻转动画
- 1.2 用2D效果做翻转动画【实际是缩小-放大,看上去是翻转】
-
2.业务分析:两个界面放在同一个布局中
- 2.1 布局设计思路分析
- 2.2 代码展示
-
3.具体动画逻辑做法:看具体代码
- 3.1 定义3D旋转动画
- 3.2 在activity处理翻转逻辑
- 3.3 直接展示2D动画实现上面需求的代码
-
4.关于Activity实现切换的方式
- 4.1 实现切换的方式
- 4.2 activity退出动画与显示动画
-
5.使用overridePendingTransition方法实现Activity跳转动画
- 5.1 如何实现,步骤演示
- 5.2 源码分析
-
6.使用style的方式定义Activity的切换动画
- 6.1 定义包含动画的 Activity 主题
- 6.2 定义切换动画 style
- 6.3 定义具体动画文件
- 6.4 应用到对应 Activity
- 6.5 可能出现的bug
- 6.5.1 添加动画后,出现从黑屏到新activity的过度
- 6.5.2 没有动画,或动画与设置不一致
-
7.使用ActivityOptions切换动画实现Activity跳转动画
- 7.1 这种动画方式介绍
- 7.2 代码实现方式
-
8.使用ActivityOptions之后内置的动画效果通过style的方式
- 8.1 定义动画文件
- 8.2 定义切换动画style
- 8.3 执行跳转逻辑
-
9.使用ActivityOptions动画共享组件的方式实现跳转Activity动画
- 9.1 定义共享组件
- 9.2 调用startActivity执行跳转动画
- 9.3 关于这几种方式的动画总结
-
10.其他说明
- 10.1 参考案例
- 10.2 更新日志
- 10.3 关于我的博客
好消息
- 博客笔记大汇总【16年3月到至今】,包括Java基础及深入知识点,Android技术博客,Python学习笔记等等,还包括平时开发中遇到的bug汇总,当然也在工作之余收集了大量的面试题,长期更新维护并且修正,持续完善……开源的文件是markdown格式的!同时也开源了生活博客,从12年起,积累共计47篇[近20万字],转载请注明出处,谢谢!
- 链接地址:https://github.com/yangchong211/YCBlogs
- 如果觉得好,可以star一下,谢谢!当然也欢迎提出建议,万事起于忽微,量变引起质变!
1.业务需求与实现方法
-
1.0 具体业务需求
- 这个动画效果是把Activity当做一张纸,正反面都有内容,Activity都会以屏幕中心为翻转中心点(Z轴的翻转中心点可以自由设定),进行旋转。
- 图形如下所示
-
1.1 用3D效果做翻转动画
- 下面2,3均是分析如何实现这种动画
-
1.2 用2D效果做翻转动画【实际是缩小-放大,看上去是翻转】
- 比较简单,效果也还不错,直接在看4.3 直接展示2D动画实现上面需求的代码
-
1.4 代码案例展示
- https://github.com/yangchong211/YCAudioPlayer
- 直接找到代码中的这几个类
1.SplashAdFirstActivity,3d效果,沿中心x,y轴旋转,可以设置缩放效果,只需要设置z轴位移就可以
2.SplashAdSecondActivity,3d效果,借鉴与网络,不是旋转的动画,但是效果很炫
3.SplashAdThirdActivity,2d效果。看上去像是旋转,实则是缩放效果。几乎看上去效果和1类似
由于产品需求,后来采用第三种方法
2.业务分析
-
2.1 布局设计思路分析
- 这个动画效果的思路是这样的,首先两个界面的布局都在同一个Layout文件中,因为这里只有一个Activity,所以两个界面的布局在同一个layout文件中就要有所设计。
-
2.2 代码展示
- 注意,在两个RelativeLayout中必须添加android:focusable=”true” ,android:focusableInTouchMode=”true”这两个属性来隔离两个界面的监听事件,使得当前显示的一面监听有效,另一个不显示的页面的监听无效,否则点击事件会乱套。
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:id="@+id/fl"
android:layout_width="match_parent"
android:layout_height="match_parent">
<!--启动页-->
<FrameLayout
android:id="@+id/fl_ad"
android:visibility="visible"
android:focusable="true"
android:focusableInTouchMode="true"
android:layout_width="match_parent"
android:layout_height="match_parent">
<ImageView
android:id="@+id/iv_ad"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@drawable/icon_bg_ad"/>
<TextView
android:id="@+id/tv_time"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="end"
android:layout_margin="20dp"
android:padding="5dp"
android:text="倒计时2秒"
android:textSize="14sp"
android:textColor="@color/blackText"
android:background="@drawable/shape_bg"/>
</FrameLayout>
<!--主页面-->
<FrameLayout
android:id="@+id/fl_main"
android:visibility="gone"
android:focusable="true"
android:focusableInTouchMode="true"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<include layout="@layout/activity_local_music_info"/>
</FrameLayout>
</LinearLayout>
3.具体动画逻辑做法:看具体代码
-
3.1 定义3D旋转动画
- 翻转效果的设计,首先是确定翻转中心点的位置,通过传入X,Y,Z三个轴的中心点来确定。然后使用Camera根据传入的翻转度来进行翻转,翻转的类Rotate3D代码如下:
public class Rotate3D extends Animation {
// 开始角度
private final float mFromDegrees;
// 结束角度
private final float mToDegrees;
// X轴中心点
private final float mCenterX;
// Y轴中心点
private final float mCenterY;
// Z轴中心点
private final float mDepthZ;
//是否需要扭曲
private final boolean mReverse;
//摄像头
private Camera mCamera;
public Rotate3D(float fromDegrees, float toDegrees, float centerX,float centerY, float depthZ, boolean reverse) {
mFromDegrees = fromDegrees;
mToDegrees = toDegrees;
mCenterX = centerX;
mCenterY = centerY;
mDepthZ = depthZ;
mReverse = reverse;
}
@Override
public void initialize(int width, int height, int parentWidth, int parentHeight) {
super.initialize(width, height, parentWidth, parentHeight);
mCamera = new Camera();
}
@Override
protected void applyTransformation(float interpolatedTime, Transformation t) {
final float fromDegrees = mFromDegrees;
// 生成中间角度
float degrees = fromDegrees + ((mToDegrees - fromDegrees) * interpolatedTime);
final float centerX = mCenterX;
final float centerY = mCenterY;
final Camera camera = mCamera;
//取得当前矩阵
final Matrix matrix = t.getMatrix();
camera.save();
if (mReverse) {
camera.translate(0.0f, 0.0f, mDepthZ * interpolatedTime);
} else {
camera.translate(0.0f, 0.0f, mDepthZ * (1.0f - interpolatedTime));
}
//翻转
camera.rotateY(degrees);
// 取得变换后的矩阵
camera.getMatrix(matrix);
camera.restore();
matrix.preTranslate(-centerX, -centerY);
matrix.postTranslate(centerX, centerY);
}
}
-
3.2 在activity处理翻转逻辑
- 整个翻转过程分为两个阶段操作,第一阶段是从当前页面翻转到整个Activity垂直于手机屏幕(到这个时刻,正反两面都是不可见的)。第二阶段是从当前的整个Activity垂直于手机屏幕(到这个时刻,正反两面都是不可见的)状态翻转到第二个页面显示在手机屏幕上。
- 代码如下所示
public class SplashAdFirstActivity extends BaseActivity {
@Bind(R.id.iv_ad)
ImageView ivAd;
@Bind(R.id.tv_time)
TextView tvTime;
//页面翻转容器FrameLayout
@Bind(R.id.fl)
LinearLayout fl;
//布局1界面RelativeLayout
@Bind(R.id.fl_ad)
FrameLayout flAd;
//布局2界面RelativeLayout
@Bind(R.id.fl_main)
FrameLayout flMain;
private TimeCount timeCount;
private boolean isClick = false;
//z轴翻转
private float z = 200.0f;
@Override
protected void onDestroy() {
super.onDestroy();
if (timeCount != null) {
timeCount.cancel();
timeCount = null;
}
}
@Override
public int getContentView() {
return R.layout.activity_splash_ad;
}
@Override
public void initView() {
initTimer();
}
private void initTimer() {
timeCount = new TimeCount(5 * 1000, 1000, tvTime);
timeCount.start();
}
@Override
public void initListener() {
ivAd.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
isClick = true;
applyRotation(1,0,90);
//applyRotation(0,0,-90);
}
});
}
@Override
public void initData() {
}
private class TimeCount extends CountDownTimer {
private TextView tv;
TimeCount(long millisInFuture, long countDownInterval, TextView tv) {
super(millisInFuture, countDownInterval);
//参数依次为总时长,和计时的时间间隔
this.tv = tv;
}
//计时完毕时触发
@Override
public void onFinish() {
//如果是点击了翻转,那么就不执行这里面的代码
if(!isClick){
//第一阶段翻转
applyRotation(1,0,90);
//applyRotation(0,0,-90);
}
}
@Override
public void onTick(long millisUntilFinished) {
//计时过程显示
StringBuilder sb = new StringBuilder();
sb.append("倒计时");
sb.append(millisUntilFinished / 1000);
sb.append("秒");
tv.setText(sb.toString());
}
}
/**
* 执行翻转第一阶段翻转动画
* @param tag view索引
* @param start 起始角度
* @param end 结束角度
*/
private void applyRotation(int tag, float start, float end) {
// 得到中心点(以中心翻转)
//X轴中心点
final float centerX = fl.getWidth() / 2.0f;
//Y轴中心点
final float centerY = fl.getHeight() / 2.0f;
//Z轴中心点
final float depthZ = z;
// 根据参数创建一个新的三维动画,并且监听触发下一个动画
final Rotate3D rotation = new Rotate3D(start, end, centerX, centerY, depthZ, true);
//设置动画持续时间
rotation.setDuration(2500);
//设置动画变化速度
//rotation.setInterpolator(new AccelerateInterpolator());
//设置第一阶段动画监听器
rotation.setAnimationListener(new DisplayNextView(tag));
fl.startAnimation(rotation);
}
/**
* 第一阶段动画监听器
*/
private final class DisplayNextView implements Animation.AnimationListener {
private final int tag;
private DisplayNextView(int tag) {
this.tag = tag;
}
@Override
public void onAnimationStart(Animation animation) {}
@Override
public void onAnimationEnd(Animation animation) {
//第一阶段动画结束时,也就是整个Activity垂直于手机屏幕,
//执行第二阶段动画
fl.post(new SwapViews(tag));
//调整两个界面各自的visibility
adjustVisibility();
}
@Override
public void onAnimationRepeat(Animation animation) {
}
}
/**
* 执行翻转第二个阶段动画
*/
private final class SwapViews implements Runnable {
private final int tag;
SwapViews(int position) {
tag = position;
}
@Override
public void run() {
if (tag == 0) {
//首页页面以90~0度翻转
showView(flAd, flMain, 90, 0);
} else if (tag == 1) {
//音乐页面以-90~0度翻转
showView(flMain, flAd, -90, 0);
}
}
}
/**
* 显示第二个视图动画
* @param showView 要显示的视图
* @param hiddenView 要隐藏的视图
* @param startDegree 开始角度
* @param endDegree 目标角度
*/
private void showView(FrameLayout showView, FrameLayout hiddenView, int startDegree, int endDegree) {
//同样以中心点进行翻转
float centerX = showView.getWidth() / 2.0f;
float centerY = showView.getHeight() / 2.0f;
float centerZ = z;
if (centerX == 0 || centerY == 0) {
//调用该方法getMeasuredWidth(),必须先执行measure()方法,否则会出异常。
showView.measure(View.MeasureSpec.UNSPECIFIED, View.MeasureSpec.UNSPECIFIED);
//获取该view在父容器里面占的大小
centerX = showView.getMeasuredWidth() / 2.0f;
centerY = showView.getMeasuredHeight() / 2.0f;
}
hiddenView.setVisibility(View.GONE);
showView.setVisibility(View.VISIBLE);
Rotate3D rotation = new Rotate3D(startDegree, endDegree, centerX, centerY, centerZ, true);
//设置动画持续时间
rotation.setDuration(2500);
//设置动画变化速度
//rotation.setInterpolator(new DecelerateInterpolator());
fl.startAnimation(rotation);
}
/**
* 两个布局的visibility调节
*/
private void adjustVisibility(){
if(flAd.getVisibility() == View.VISIBLE){
flAd.setVisibility(View.GONE);
}else {
flMain.setVisibility(View.VISIBLE);
}
if(flMain.getVisibility() == View.VISIBLE){
flMain.setVisibility(View.GONE);
}else {
flAd.setVisibility(View.VISIBLE);
}
}
}
- 3.3 直接展示2D动画实现上面需求的代码
public class SplashAdThirdActivity extends BaseActivity {
@Bind(R.id.fl_ad)
FrameLayout flAd;
@Bind(R.id.fl_main)
FrameLayout flMain;
@Bind(R.id.fl)
LinearLayout fl;
@Bind(R.id.iv_ad)
ImageView ivAd;
@Bind(R.id.tv_time)
TextView tvTime;
private TimeCount timeCount;
private boolean isClick = false;
private ScaleAnimation sato0 = new ScaleAnimation(1,0,1,1,
Animation.RELATIVE_TO_PARENT,0.5f, Animation.RELATIVE_TO_PARENT,0.5f);
private ScaleAnimation sato1 = new ScaleAnimation(0,1,1,1,
Animation.RELATIVE_TO_PARENT,0.5f,Animation.RELATIVE_TO_PARENT,0.5f);
@Override
protected void onDestroy() {
super.onDestroy();
if (timeCount != null) {
timeCount.cancel();
timeCount = null;
}
}
@Override
public int getContentView() {
return R.layout.activity_splash_ad;
}
@Override
public void initView() {
initTimer();
}
private void initTimer() {
timeCount = new TimeCount(5 * 1000, 1000, tvTime);
timeCount.start();
}
@Override
public void initListener() {
ivAd.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
isClick = true;
flAd.startAnimation(sato0);
}
});
}
@Override
public void initData() {
showView1();
sato0.setDuration(500);
sato1.setDuration(500);
sato0.setAnimationListener(new Animation.AnimationListener() {
@Override
public void onAnimationStart(Animation animation) {
}
@Override
public void onAnimationEnd(Animation animation) {
if (flAd.getVisibility() == View.VISIBLE){
flAd.setAnimation(null);
showView2();
flMain.startAnimation(sato1);
}else{
flMain.setAnimation(null);
showView1();
flAd.startAnimation(sato1);
}
}
@Override
public void onAnimationRepeat(Animation animation) {
}
});
}
private class TimeCount extends CountDownTimer {
private TextView tv;
TimeCount(long millisInFuture, long countDownInterval, TextView tv) {
super(millisInFuture, countDownInterval);
//参数依次为总时长,和计时的时间间隔
this.tv = tv;
}
//计时完毕时触发
@Override
public void onFinish() {
//如果是点击了翻转,那么就不执行这里面的代码
if(!isClick){
//第一阶段翻转
flAd.startAnimation(sato0);
}
}
@Override
public void onTick(long millisUntilFinished) {
//计时过程显示
StringBuilder sb = new StringBuilder();
sb.append("倒计时");
sb.append(millisUntilFinished / 1000);
sb.append("秒");
tv.setText(sb.toString());
}
}
private void showView1(){
flAd.setVisibility(View.VISIBLE);
flMain.setVisibility(View.GONE);
}
private void showView2(){
flAd.setVisibility(View.GONE);
flMain.setVisibility(View.VISIBLE);
}
}
4.关于Activity实现切换的方式
-
4.1 实现切换的方式
- 调用startActivity方法启动一个新的Activity并跳转其页面
- 调用finish方法销毁当前的Activity返回上一个Activity界面
-
4.2 activity退出动画与显示动画
- 当调用startActivity方法的时候启动一个新的activity,这时候就涉及到了旧的Activity的退出动画和新的Activity的显示动画;
- 当调用finish方法的时候,销毁当前Acitivity,就涉及到了当前Activity的退出动画和前一个Activity的显示动画;
- 所以我们的activity跳转动画是分为两个部分的:一个Activity的销毁动画与一个Activity的显示动画,明白了这一点之后我们开始看一下第一种实现Activity跳转动画的方式:通过overridePendingTransition方法实现Activity切换动画。
5.使用overridePendingTransition方法实现Activity跳转动画
-
5.1 如何实现,步骤演示
- overridePendingTransition方法是Activity中提供的Activity跳转动画方法,通过该方法可以实现Activity跳转时的动画效果。
- 可以直接参考我的项目:https://github.com/yangchong211/YCVideoPlayer或者https://github.com/yangchong211/YCAudioPlayer
- 具体代码如下所示
Intent intent = new Intent(this, MainActivity.class);
startActivity(intent);
overridePendingTransition(R.anim.screen_zoom_in, R.anim.screen_zoom_out);
finish();
- 动画代码如下所示
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
android:interpolator="@android:anim/accelerate_interpolator">
<scale
android:duration="@android:integer/config_mediumAnimTime"
android:fromXScale="2.0"
android:fromYScale="2.0"
android:pivotX="50%p"
android:pivotY="50%p"
android:toXScale="1.0"
android:toYScale="1.0" />
<alpha
android:duration="@android:integer/config_mediumAnimTime"
android:fromAlpha="0"
android:toAlpha="1.0" />
</set>
-
5.2 源码分析
- 看下面这一段注释可以知道:
- overridePendingTransition方法需要在startAtivity方法或者是finish方法调用之后立即执行
- 参数enterAnim表示的是从Activity a跳转到Activity b,进入b时的动画效果
- 参数exitAnim表示的是从Activity a跳转到Activity b,离开a时的动过效果
- 若进入b或者是离开a时不需要动画效果,则可以传值为0
- 看下面这一段注释可以知道:
/**
* Call immediately after one of the flavors of {@link #startActivity(Intent)}
* or {@link #finish} to specify an explicit transition animation to
* perform next.
*
* <p>As of {@link android.os.Build.VERSION_CODES#JELLY_BEAN} an alternative
* to using this with starting activities is to supply the desired animation
* information through a {@link ActivityOptions} bundle to
* {@link #startActivity(Intent, Bundle)} or a related function. This allows
* you to specify a custom animation even when starting an activity from
* outside the context of the current top activity.
*
* @param enterAnim A resource ID of the animation resource to use for
* the incoming activity. Use 0 for no animation.
* @param exitAnim A resource ID of the animation resource to use for
* the outgoing activity. Use 0 for no animation.
*/
public void overridePendingTransition(int enterAnim, int exitAnim) {
try {
ActivityManagerNative.getDefault().overridePendingTransition(
mToken, getPackageName(), enterAnim, exitAnim);
} catch (RemoteException e) {
}
}
6.使用style的方式定义Activity的切换动画
-
6.1 定义包含动画的 Activity 主题
- 在res/values/styles.xml文件中
<style name="AnimActivityTheme" parent="@android:style/Animation.Activity">
<item name="android:windowAnimationStyle">@style/MyWindowAnimTheme</item>
</style>
-
6.2 定义切换动画 style
- 还是res/values/styles.xml 文件中
- activityOpenEnterAnimation // 用于设置打开新的Activity并进入新的Activity展示的动画
- activityOpenExitAnimation // 用于设置打开新的Activity并销毁之前的Activity展示的动画
- activityCloseEnterAnimation // 用于设置关闭当前Activity进入上一个Activity展示的动画
- activityCloseExitAnimation // 用于设置关闭当前Activity时展示的动画
- 还是res/values/styles.xml 文件中
<style name="MyWindowAnimTheme">
<item name="android:activityOpenEnterAnimation">@anim/top_to_bottom_in</item>
<item name="android:activityOpenExitAnimation">@anim/top_to_bottom_out</item>
<item name="android:activityCloseEnterAnimation">@anim/bottom_to_top_in</item>
<item name="android:activityCloseExitAnimation">@anim/bottom_to_top_out</item>
</style>
-
6.3 定义具体动画文件
- res/anmi/res/top_to_bottom_in.xml
- res/anmi/res/top_to_bottom_out.xml
- res/anmi/res/bottom_to_top_in.xml
- res/anmi/res/bottom_to_top_out.xml
-
6.4 应用到对应 Activity
- 在清单文件中添加
<activity android:name=".MainActivity"
android:theme="@style/AnimActivityTheme”>
-
6.5 可能出现的bug
- 6.5.1 添加动画后,出现从黑屏到新activity的过度
- 问题:添加动画后,出现从黑屏到新activity的过度。
- 原因:没有设置相应的消失动画。
- 解决方法:设置相应的消失动画,如果不想设置消失动画,可以使用写一个假动画,这个动画是没有任何效果,只是为了避免出现黑屏,运行效果为原acticity静止不动,新启动的activity执行进入动画。
- 6.5.2 没有动画,或动画与设置不一致
- 问题:没有动画,或动画与设置不一致
- 原因:当页面切换时需要进入和消失两个动画,当没有进入动画时,消失动画也不会执行,会执行系统动画,如果没有系统动画则没有动画,或者某个页面使用第一或第二种方式设置了动画(动画执行优先级,系统动画 < AppTheme < (overridePendingTransition\ActivityOptionsCompat))。
- 解决方法:为了保证进入和消失都有动画,要将动画主题设置到两个Activity上。也可以将主题设置到application上,这样整个应用都是用该切换动画。如果是某个页面使用第一或第二种方式设置了动画,那么在启动和退出时最好都要设置,不然会造成启动和退出不一致的情况。
- 6.5.1 添加动画后,出现从黑屏到新activity的过度
7.使用ActivityOptions切换动画实现Activity跳转动画
-
7.1 这种动画方式介绍
- 上面我们讲解的通过overridePendingTransition方法基本上可以满足我们日常中对Activity跳转动画的需求了,但是MD风格出来之后,overridePendingTransition这种老旧、生硬的方式怎么能适合我们的MD风格的App呢?好在google在新的sdk中给我们提供了另外一种Activity的过度动画——ActivityOptions。并且提供了兼容包——ActivityOptionsCompat。ActivityOptionsCompat是一个静态类,提供了相应的Activity跳转动画效果,通过其可以实现不少炫酷的动画效果。
-
7.2 代码实现方式
- 代码诠释
- 传入了ActivityOptions.makeSceneTransitionAnimation,该方法表示将Activity a平滑的切换到Activity b,其还有几个重载方法可以指定相关的View,即以View为焦点平滑的从Activity a切换到Activity b。
- 这里的setFeature就是为activity的窗口设置特性,不同的特性对应不同的布局方式,比如可以设置无toolbar模式,有toolbar模式等等。而这里设置的是需要过渡动画,并且我们获取了Android中内置的explode动画,并设值给了Activity的window窗口对象,这样当Activity被启动的时候就会执行explode所带便的动画效果了。
- 在startActivity页面
- 代码诠释
Intent intent = new Intent(MainActivity.this, ThreeActivity.class);
startActivity(intent, ActivityOptions.makeSceneTransitionAnimation(MainActivity.this).toBundle());
- 在跳转后的页面
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// 设置contentFeature,可使用切换动画
getWindow().requestFeature(Window.FEATURE_CONTENT_TRANSITIONS);
Transition explode = TransitionInflater.from(this).inflateTransition(Android.R.transition.explode);
getWindow().setEnterTransition(explode);
setContentView(R.layout.activity_main);
}
8.使用ActivityOptions之后内置的动画效果通过style的方式
-
8.1 定义动画文件
- 这种方式其实就是通过style的方式展示和使用ActivityOptions过度动画,下面是实现通过定义style方式定义过度动画的步骤:
- res目录下新建一个transition目录,然后创建资源文件,然后使用这些系统自带的过渡动画效果,这里设置了过度时长为300ms
<explode xmlns:Android="http://schemas.Android.com/apk/res/Android"
Android:duration="300" />
- 8.2 定义切换动画style
<style name="AppAnimTheme">
<item name="Android:windowEnterTransition">@transition/activity_explode</item>
<item name="Android:windowExitTransition">@transition/activity_explode</item>
</style>
<item name="Android:windowEnterTransition">@transition/activity_explode</item>
<item name="Android:windowExitTransition">@transition/activity_explode</item>
- 8.3 执行跳转逻辑
/**
* 点击按钮,实现Activity的跳转操作
* 通过Android5.0及以上style的方式实现activity的跳转动画
*/
/**
* 调用ActivityOptions.makeSceneTransitionAnimation实现过度动画
*/
Intent intent = new Intent(MainActivity.this, FourActivity.class);
startActivity(intent, ActivityOptions.makeSceneTransitionAnimation(MainActivity.this).toBundle());
9.使用ActivityOptions动画共享组件的方式实现跳转Activity动画
- 这里的共享组件动画效果是指将前面一个Activity的某个子View与后面一个Activity的某个子View之间有过渡效果,即在这种过度效果下实现Activity的跳转操作。那么如何实现两个组件View之间实现过渡效果呢?
-
9.1 定义共享组件
- 在Activity a中的button按钮点击transitionName属性:
<Button
Android:layout_width="match_parent"
Android:layout_height="wrap_content"
Android:text="组件过度动画"
Android:transitionName="shareNames"/>
- 在Activity b的布局文件中为组件定义transitionName属性,这样这两个组件相当于有了过度对应关系,这里需要注意的是这两个组件的transitionName属性的值必须是相同的。
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:Android="http://schemas.Android.com/apk/res/Android"
Android:layout_width="match_parent"
Android:layout_height="match_parent"
Android:orientation="vertical"
Android:transitionName="shareNames">
</LinearLayout>
-
9.2 调用startActivity执行跳转动画
- 需要说明的是这里调用的ActivityOptions.makeSceneTransitionAnimation方法,传递了三个参数,其中第一个参数为context对象,第二个参数为启动Activity的共享组件,第三个参数为启动Activity的共享组件transitionName属性值。
/**
* 点击按钮,实现Activity的跳转操作
* 通过Android5.0及以上共享组件的方式实现activity的跳转动画
*/
Intent intent = new Intent(MainActivity.this, FiveActivity.class);
startActivity(intent, ActivityOptions.makeSceneTransitionAnimation(MainActivity.this, button, "shareNames").toBundle());
-
9.3 关于这几种方式的动画总结
- 通过overridePendingTransition方式和ActivityOptions动画API实现Activity的切换动画效果;
- overridePendingTransition方法从Android2.0开始,基本上能够覆盖我们activity跳转动画的需求;
- ActivityOptions API是在Android5.0开始的,可以实现一些炫酷的动画效果,更加符合MD风格;
- ActivityOptions还可以实现两个Activity组件之间的过度动画;
10.其他说明
- 10.1 参考案例
-
10.2 更新日志
- v1.0.0 更新于2017年3月19日
- v1.0.1 更新于2018年1月5日
- 10.3 关于我的博客
网友评论