Github项目解析(九)–>实现Activity跳转动画的五种方式

Github项目解析(九)–>实现Activity跳转动画的五种方式文本中我们将讲解activity切换动画相关的知识点,这里的切换动画指的是是activity跳转时的动画效果。这里总结了一下,有五种方式实现activity切换时实现动画效果。下面我将依次介绍一下每种实现activity切换动画效果的实现方式

大家好,又见面了,我是你们的朋友全栈君。

转载请标明出处:一片枫叶的专栏

上一篇文章中我们讲解了在Activity启动过程中获取组件宽高的五种方式。在Activity的启动过程中如果我们直接在生命周期方法中通过view.getWidth()或者是view.getHeight()方法获取组件的宽度和高度其结果都是0,为什么会出现这个问题呢?

其实看过我以前写过的Activity启动流程  Activity布局加载流程  Activity布局绘制流程  的同学应该对Activity的启动流程和其布局加载绘制流程不陌生,Activity的启动流程和Activity的布局文件加载绘制流程,其实没有相关的关系的,其实两个异步的加载流程,这样我们在Activity的onCreate或者是onResume方法中调用textView.getHeight()或者是textView.getWidth()方法的时候,Activity对应的组件并没有执行完绘制流程,因此此时获取到的组件的宽高都是默认的0,所以这时候通过getWidth()和getHeight()方法也就是无法获取组件的宽和高了。

更多关于在Activity启动过程中获取组件宽高的知识,可参考我的:Activity启动过程中获取组件宽高的N种方式

文本中我们将讲解activity切换动画相关的知识点,这里的切换动画指的是是activity跳转时的动画效果。这里总结了一下,有五种方式实现activity切换时实现动画效果。下面我将依次介绍一下每种实现activity切换动画效果的实现方式。

在介绍activity的切换动画之前我们先来说明一下实现切换activity的两种方式:

  • 调用startActivity方法启动一个新的Activity并跳转其页面

  • 调用finish方法销毁当前的Activity返回上一个Activity界面

当调用startActivity方法的时候启动一个新的activity,这时候就涉及到了旧的Activity的退出动画和新的Activity的显示动画;
当调用finish方法的时候,销毁当前Acitivity,就涉及到了当前Activity的退出动画和前一个Activity的显示动画;

所以我们的activity跳转动画是分为两个部分的:一个Activity的销毁动画与一个Activity的显示动画,明白了这一点之后我们开始看一下第一种实现Activity跳转动画的方式:通过overridePendingTransition方法实现Activity切换动画。

(一)使用overridePendingTransition方法实现Activity跳转动画

overridePendingTransition方法是Activity中提供的Activity跳转动画方法,通过该方法可以实现Activity跳转时的动画效果。下面我们就将通过一个简单的例子看一下如何通过overridePendingTransition方法实现Activity的切换动画。

demo例子中我们实现了Activity a中有一个点击按钮,点击按钮实现跳转Activity b的逻辑,具体代码如下:

/** * 点击按钮实现跳转逻辑 */
button1.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                /** * 在调用了startActivity方法之后立即调用overridePendingTransition方法 */
                Intent intent = new Intent(MainActivity.this, SecondActivity.class);
                startActivity(intent);
                overridePendingTransition(R.anim.slide_in_left, R.anim.slide_in_left);
            }
        });

可以看到我们在调用了startActivity方法之后又执行了overridePendingTransition方法,而在overridePendingTransition方法中传递了两个动画布局文件,我们首先看一下这里的动画文件具体是怎么实现的:

<?xml version="1.0" encoding="utf-8"?>
<set xmlns:Android="http://schemas.Android.com/apk/res/Android" Android:shareInterpolator="false" Android:zAdjustment="top">
    <translate  Android:duration="200" Android:fromXDelta="-100.0%p" Android:toXDelta="0.0" />
</set>

这里的overridePendingTransition方法传递的是两个动画文件id,第一个参数是需要打开的Activity进入时的动画,第二个参数是需要关闭的Activity离开时的动画。这样我们执行了这段代码之后在跳转Activity的时候就展示了动画效果:
这里写图片描述

动画的效果是通过overridePendingTransition方法实现的,那么下面我们来看一下overridePendingTransition方法的定义,我们在overridependingTransition方法在定义的时候有这样的一段注释说明:

/** * Call immediately after one of the flavors of { 
   @link #startActivity(Intent)} * or { 
   @link #finish} to specify an explicit transition animation to * perform next. */

/** * @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. */

好吧,这段注释,告诉通过注释我们能够知道:

  • overridePendingTransition方法需要在startAtivity方法或者是finish方法调用之后立即执行

  • 参数enterAnim表示的是从Activity a跳转到Activity b,进入b时的动画效果

  • 参数exitAnim表示的是从Activity a跳转到Activity b,离开a时的动过效果

  • 若进入b或者是离开a时不需要动画效果,则可以传值为0

好吧,本着批判的精神,我们来看一下是不是这样的,首先看一下如果我们在startActivity方法调用之后不立即执行overridePendingTransition方法,会有动画效果么?

若我们将overridePendingTransition延时1s执行呢?

/** * 点击按钮实现跳转逻辑 */
button1.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Intent intent = new Intent(MainActivity.this, SecondActivity.class);
                startActivity(intent);
                overridePendingTransition(R.anim.slide_in_left, R.anim.slide_out_left);
                /** * 延时1s执行overridePendingTransition方法 */
                button1.postDelayed(new Runnable() {
                    @Override
                    public void run() {
                        overridePendingTransition(R.anim.slide_in_top, R.anim.slide_in_top);
                    }
                }, 1000);

            }
        });

好吧,执行之后我们能够发现跳转动画没有了,所以overridePendingTransition只能在startActivity或者是finish方法之后执行。

还有一个问题,如果是在startActivity之后执行,只是在子线程中执行呢?activity的跳转动画能够执行么?

/** * 点击按钮实现跳转逻辑 */
button1.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Intent intent = new Intent(MainActivity.this, SecondActivity.class);
                startActivity(intent);
                overridePendingTransition(R.anim.slide_in_left, R.anim.slide_out_left);
                /** * 在子线程中执行overridePendingTransition方法 */
                new Thread(new Runnable() {
                    @Override
                    public void run() {
                        overridePendingTransition(R.anim.slide_in_left, R.anim.slide_out_left);
                    }
                }).start();

            }
        });

好吧,你没有猜错,activity的切换效果还是执行,也就是说overridePendingTransition方法也是可以在子线程中执行的,当然这并没什么卵用。

好吧,在介绍完了使用overridePendingTransition方法实现Activity切换动画之后我们下面看一下使用style的方式定义实现Activity的切换动画。

(二)使用style的方式定义Activity的切换动画

(1)定义Application的style

<!-- 系统Application定义 -->
<application  Android:allowBackup="true" Android:icon="@mipmap/ic_launcher" Android:label="@string/app_name" Android:supportsRtl="true" Android:theme="@style/AppTheme">

(2)定义具体的AppTheme样式

其中这里的windowAnimationStyle就是我们定义Activity切换动画的style。而@anim/slide_in_top就是我们定义的动画文件,也就是说通过为Appliation设置style,然后为windowAnimationStyle设置动画文件就可以全局的为Activity的跳转配置动画效果。

<!-- Base application theme. -->
    <style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar"> <!-- Customize your theme here. --> <item name="colorPrimary">@color/colorPrimary</item> <item name="colorPrimaryDark">@color/colorPrimaryDark</item> <item name="colorAccent">@color/colorAccent</item> <item name="Android:windowAnimationStyle">@style/activityAnim</item> </style>


<!-- 使用style方式定义activity切换动画 -->
    <style name="activityAnim"> <item name="Android:activityOpenEnterAnimation">@anim/slide_in_top</item> <item name="Android:activityOpenExitAnimation">@anim/slide_in_top</item> </style>

而在windowAnimationStyle中存在四种动画:

activityOpenEnterAnimation // 用于设置打开新的Activity并进入新的Activity展示的动画
activityOpenExitAnimation  // 用于设置打开新的Activity并销毁之前的Activity展示的动画
activityCloseEnterAnimation  // 用于设置关闭当前Activity进入上一个Activity展示的动画
activityCloseExitAnimation  // 用于设置关闭当前Activity时展示的动画

(3)测试代码,实现activity切换操作

/** * 点击按钮,实现Activity的跳转操作 * 通过定义style的方式实现activity的跳转动画 */
        button2.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                /** * 普通的Intent跳转Activity实现 */
                Intent intent = new Intent(MainActivity.this, SecondActivity.class);
                startActivity(intent);
            }
        });

这时候我们我们执行diamante逻辑之后就能发现activity在切换的时候出现了动画效果,说明我们设置的style起作用了。

(三)使用ActivityOptions切换动画实现Activity跳转动画

上面我们讲解的通过overridePendingTransition方法基本上可以满足我们日常中对Activity跳转动画的需求了,但是MD风格出来之后,overridePendingTransition这种老旧、生硬的方式怎么能适合我们的MD风格的App呢?好在google在新的sdk中给我们提供了另外一种Activity的过度动画——ActivityOptions。并且提供了兼容包——ActivityOptionsCompat。ActivityOptionsCompat是一个静态类,提供了相应的Activity跳转动画效果,通过其可以实现不少炫酷的动画效果。

(1)在跳转的Activity中设置contentFeature

@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_three);
    }

这里我们在Activity的setContentView之前调用了:

getWindow().requestFeature(Window.FEATURE_CONTENT_TRANSITIONS);

方法,看过我的Activity布局加载流程的同学应该知道,这里的setFeature就是为activity的窗口设置特性,不同的特性对应不同的布局方式,比如可以设置无toolbar模式,有toolbar模式等等。而这里设置的是需要过渡动画,并且我们获取了Android中内置的explode动画,并设值给了Activity的window窗口对象,这样当Activity被启动的时候就会执行explode所带便的动画效果了。

(2)在startActivity执行跳转逻辑的时候调用startActivity的重写方法,执行ActivityOptions.makeSceneTransitionAnimation方法

/** * 点击按钮,实现Activity的跳转操作 * 通过Android5.0及以上代码的方式实现activity的跳转动画 */
        button3.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Intent intent = new Intent(MainActivity.this, ThreeActivity.class);
                startActivity(intent, ActivityOptions.makeSceneTransitionAnimation(MainActivity.this).toBundle());
            }
        });

这里我们调用了startActivity的重载方法:

public void startActivity(Intent intent, @Nullable Bundle options)

并且我们传入了ActivityOptions.makeSceneTransitionAnimation,该方法表示将Activity a平滑的切换到Activity b,其还有几个重载方法可以指定相关的View,即以View为焦点平滑的从Activity a切换到Activity b。

调用这段代码之后我们activity跳转的时候就展示出了动画效果。
这里写图片描述

(四)使用ActivityOptions之后内置的动画效果通过style的方式

这种方式其实就是通过style的方式展示和使用ActivityOptions过度动画,下面是实现通过定义style方式定义过度动画的步骤:

(1)编写过度动画文件

<explode xmlns:Android="http://schemas.Android.com/apk/res/Android"
    Android:duration="300" />

首先我们需要在Application项目res目录下新建一个transition目录,然后创建资源文件,然后使用这些系统自带的过渡动画效果,这里设置了过度时长为300ms。

(2)定义style文件

<!-- Base application theme. -->
    <style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
        <!-- Customize your theme here. -->
        <item name="colorPrimary">@color/colorPrimary</item>
        <item name="colorPrimaryDark">@color/colorPrimaryDark</item>
        <item name="colorAccent">@color/colorAccent</item>

        <item name="Android:windowEnterTransition">@transition/activity_explode</item>
        <item name="Android:windowExitTransition">@transition/activity_explode</item>
    </style>

在Application的style文件中添加:

<item name="Android:windowEnterTransition">@transition/activity_explode</item>
        <item name="Android:windowExitTransition">@transition/activity_explode</item>

并指定过渡动画效果为我们刚刚定义的过渡动画文件。

(3)执行跳转逻辑

/** * 点击按钮,实现Activity的跳转操作 * 通过Android5.0及以上style的方式实现activity的跳转动画 */
        button4.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                /** * 调用ActivityOptions.makeSceneTransitionAnimation实现过度动画 */
                Intent intent = new Intent(MainActivity.this, FourActivity.class);
                startActivity(intent, ActivityOptions.makeSceneTransitionAnimation(MainActivity.this).toBundle());
            }
        });

这样执行之后也可以展示出Activity跳转过度动画了,其和通过代码方式实现的效果是类似的,而且这种动画效果是全局的。

(五)使用ActivityOptions动画共享组件的方式实现跳转Activity动画

这里的共享组件动画效果是指将前面一个Activity的某个子View与后面一个Activity的某个子View之间有过渡效果,即在这种过度效果下实现Activity的跳转操作。那么如何实现两个组件View之间实现过渡效果呢?

(1)定义共享组件

在Activity a中的button按钮点击transitionName属性:

<Button
        Android:id="@+id/button5"
        Android:layout_width="match_parent"
        Android:layout_height="wrap_content"
        Android:layout_below="@+id/button4"
        Android:layout_marginTop="10dp"
        Android:layout_marginRight="10dp"
        Android:layout_marginLeft="10dp"
        Android:text="组件过度动画"
        Android:background="@color/colorPrimary"
        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:id="@+id/activity_second"
    Android:layout_width="match_parent"
    Android:layout_height="match_parent"
    Android:gravity="center_horizontal"
    Android:orientation="vertical"
    Android:transitionName="shareNames"
    >

    <TextView
        Android:layout_width="match_parent"
        Android:layout_height="match_parent"
        Android:background="@color/colorAccent"
        Android:layout_marginTop="10dp"
        Android:layout_marginBottom="10dp"
        />


</LinearLayout>

(2)调用startActivity执行跳转动画

/** * 点击按钮,实现Activity的跳转操作 * 通过Android5.0及以上共享组件的方式实现activity的跳转动画 */
        button5.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Intent intent = new Intent(MainActivity.this, FiveActivity.class);
                startActivity(intent, ActivityOptions.makeSceneTransitionAnimation(MainActivity.this, button5, "shareNames").toBundle());
            }
        });

需要说明的是这里调用的ActivityOptions.makeSceneTransitionAnimation方法,传递了三个参数,其中第一个参数为context对象,第二个参数为启动Activity的共享组件,第三个参数为启动Activity的共享组件transitionName属性值。

这样经过调用之后我们就实现了从Activity a跳转到Activity b的时候a中的组件到b中组件的过度效果。
这里写图片描述

总结:

  • 本文主要讲解了通过overridePendingTransition方式和ActivityOptions动画API实现Activity的切换动画效果;

  • overridePendingTransition方法从Android2.0开始,基本上能够覆盖我们activity跳转动画的需求;

  • ActivityOptions API是在Android5.0开始的,可以实现一些炫酷的动画效果,更加符合MD风格;

  • ActivityOptions还可以实现两个Activity组件之间的过度动画;

  • 本项目例子已上传待github中,欢迎star和follow,项目地址:实现activity跳转动画的五种方式

另外对github项目,开源项目解析感兴趣的同学可以参考我的:
Github项目解析(一)–>上传Android项目至github
Github项目解析(二)–>将Android项目发布至JCenter代码库
Github项目解析(三)–>Android内存泄露监测之leakcanary
Github项目解析(四)–>动态更改TextView的字体大小
Github项目解析(五)–>Android日志框架
Github项目解析(六)–>自定义实现ButterKnife框架
Github项目解析(七)–>防止按钮重复点击
Github项目解析(八)–>Activity启动过程中获取组件宽高的五种方式

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/143203.html原文链接:https://javaforall.net

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • pinn求解ode_pt_pin

    pinn求解ode_pt_pin今天硕士论文开题答辩,想着学了这么长时间的PINN,七七八八也看了一些文献,一来是为了整理思路,二来可以方便以后回顾复习。使用PINN求解PDE与传统有限元、有限差分、谱方法等最大的区别是,无需做预先的假设,线性化和网格化。求解一般的偏微分方程的形式:PINN具体算法步骤如下:其中只有初边界训练数据包含u的值,内部配置点不包含u的值,只有定义域内部的点。(这一点一直迷糊,最近才理清楚)。PINN求解PDE框架图:可以通过自动微分最小化损失函数,得到神经网络最优参数,从而的到.

    2025年7月13日
    2
  • Vue进阶之事件处理器[通俗易懂]

    Vue进阶之事件处理器

    2022年2月24日
    42
  • string和stringbuffer的区别面试题_stringbuffer转为string

    string和stringbuffer的区别面试题_stringbuffer转为stringString和StringBuffer的区别String:是对象不是原始类型。为不可变对象,一旦被创建,就不能修改它的值。对于已经存在的String对象的修改都是重新创建一个新的对象,然后把新的值保存进去。String是final类,即不能被继承。StringBuffer:是一个可变对象,当对它进行修改的时候不会像String那样重新建立对象。它只…

    2022年4月19日
    46
  • 这一刻,感动吧[通俗易懂]

    这一刻,感动吧[通俗易懂]我是哭了好几场啊,难道我神经脆弱?告诉我你哭了几场,我脸都洗不过来啊。不是我不懂爱情,没有爱心,不相信真情,确是这世界忙碌得很,谁与我共行?科学探索:英国一位农夫在自家花园内发现了三只瑟瑟发抖的小狐狸,于是给了它们一个毛绒玩具。没想到小家伙们把它当做了自己的妈妈,不但和它形影不离,吃饭的时候还会留下部分食物,把盆子推到它跟前好友爱的一幕!给饿了的小北极熊食物。在蛮荒之地,气候恶劣。食物不足…

    2022年7月12日
    36
  • 批处理for循环命令初步学习

    批处理for循环命令初步学习1基本格式DOS批处理for循环语句的基本格式是,for/参数%变量in(集)do命令参数:FOR分四种参数DLRF;变量:变量名是由单个字母组成且区分大小写(原帮助是这么说的,实际运用中用单个数字作为变量名试过证明也可行),如%B和%b代表的是不同的变量;FOR命令会在每次循环中,把in(集)中读取到的值赋于这个变量,以便其后的命令中引用;集:由系列文件、字符串或由命令产生的内容形成的集合(当然可用通配符*?,还可引用环…

    2022年10月12日
    3
  • VS 2017 产品密钥

    VS 2017 产品密钥个人分类 nbsp vs2010Visual VS2017 企业版 Enterprise 注册码 NJVYC BMHX2 G77MM 4XJMR 6Q8QFVisualS VS2017 专业版 Professional 激活码 key KBJFW NXHK6 W4WJM CRMQB G3CDH 启动 VS 之后 在菜单栏有个帮助的下拉框 选择注册产品

    2025年7月16日
    2

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号