美文网首页Android 技术收集
Activity过场动画干货总结

Activity过场动画干货总结

作者: 高清马里奥 | 来源:发表于2019-12-26 00:00 被阅读0次

    大纲

    大纲.png

    Activity的overridePendingTransition方法

    官方文档中说:

    Call immediately after one of the flavors of startActivity(android.content.Intent) or finish() to specify an explicit transition animation to perform next.

    文档指明overridePendingTransition必需在startActivity()或者finish()函数之后立即调用

    public void overridePendingTransition (int enterAnim, int exitAnim)
    

    overridePendingTransition()方法接收的是两个动画资源enterAnim和exitAnim。
    当通过startActivity()从A进入B时,B执行enterAnim,A执行exitAnim;
    当通过finish()从B回退A时,A执行enterAnim,B执行exitAnim。

    我们这里模仿微信的推进推出效果,创建4个过场动画文件:
    (这里注意一个点就是android:duration设置最好一致,因为如果在startActivity的时候进入enterAnim大于exitAnim,就会出现新的Activity还没有完全进入界面,而上一个页面已经滑出了导致背景全黑)
    activity_open_enter.xml 对应startActivity时的enterAnim

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

    activity_open_exit.xml 对应startActivity时的exitAnim

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

    activity_close_enter 对应finish时的enterAnim

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

    activity_close_exit 对应finish时的exitAnim

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

    我们在startActivity时

    //MainActivity.kt
    val intent = Intent(this@MainActivity, Step1Activity::class.java)
    startActivity(intent)
    overridePendingTransition( R.anim.activity_open_enter,  R.anim.activity_open_exit)
    

    finish时

    //Step1Activity.kt
    finish()
    overridePendingTransition( R.anim.activity_close_enter,  R.anim.activity_close_exit)
    

    就实现了微信的推入推出的效果


    仿微信Activity过场动画.gif

    如果不需要切换动画可以设置overridePendingTransition(0,0),注意,不要动画不是默认动画,这里不要动画是直接显示新的Activity没有任何动画效果

    另外官方文档后半部分中又引出了新的东西:

    As of Build.VERSION_CODES.JELLY_BEAN an alternative to using this with starting activities is to supply the desired animation information through a ActivityOptions bundle to startActivity(android.content.Intent, android.os.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.

    在安卓5.0之后可以创建一个携带一个动画设置的ActivityOptions,在startActivity(android.content.Intent, android.os.Bundle)时转为Bundle使用。
    文档给我们引出了一个新的东西——ActivityOptions,关于ActivityOptions的详细使用,它提供了多种动画的方法,这里暂时不多做扩展,只挑它两个使用方法先说,而且放在最后说,因为我们要先说安卓提供的另外一种过场动画的设置方法。

    theme设置windowAnimationStyle

    安卓提供了一组style属性可以直接在manifest里面设置某个Activity的过场动画,当然也可以直接设置在Application的theme上从而全局配置,这里的优先级是小于java代码中动态设置的。

    activityOpenEnterAnimation
    activityOpenExitAnimation
    activityCloseEnterAnimation
    activityCloseExitAnimation
    

    这些属性对应与上面两种场景的两对参数,属性的名称也更加易懂
    这里就以设置给Application为例创建一个WindowAnimationStyle

        <style name="WindowAnimationStyle">
            <item name="android:activityOpenEnterAnimation">@anim/activity_open_enter</item>
            <item name="android:activityOpenExitAnimation">@anim/activity_open_exit</item>
            <item name="android:activityCloseEnterAnimation">@anim/activity_close_enter</item>
            <item name="android:activityCloseExitAnimation">@anim/activity_close_exit</item>
        </style>
    

    这里我们新建了一个全屏的AppTheme作为Application的theme,将这个windowAnimationStyle设置给AppTheme

        <style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar">
            <!-- Customize your theme here. -->
            <item name="android:windowNoTitle">true</item>
            <item name="android:windowFullscreen">true</item>
            <item name="android:windowContentOverlay">@null</item>
            <item name="android:windowAnimationStyle">@style/WindowAnimationStyle</item>
        </style>
    

    在Manifest中将AppTheme设置给Application

     <application
            ......
            android:theme="@style/AppTheme">
        </application>
    

    现在app中的所有页面基本都具有相同的转场动画了。为什么说基本上,因为这样设置后不同的Activity栈之间切换仍旧是默认的动画(如果这个时候跳转launchMode是singleTask或者使用Intent.FLAG_ACTIVITY_CLEAR_TASK or Intent.FLAG_ACTIVITY_NEW_TASK作为flag的,你会发现仍旧是默认的动画的,并且默认的跨任务栈的动画有些突兀)。谷歌提供了另外一组属性设置跨Activity栈的转场动画

    taskOpenEnterAnimation
    taskOpenExitAnimation
    taskCloseEnterAnimation
    taskCloseExitAnimation
    

    我们把这几个属性在WindowAnimationStyle里面补齐,这样跨Activity栈的过场动画就也保持一致啦。

        <style name="WindowAnimationStyle">
            <item name="android:activityOpenEnterAnimation">@anim/activity_open_enter</item>
            <item name="android:activityOpenExitAnimation">@anim/activity_open_exit</item>
            <item name="android:activityCloseEnterAnimation">@anim/activity_close_enter</item>
            <item name="android:activityCloseExitAnimation">@anim/activity_close_exit</item>
    
            <item name="android:taskOpenEnterAnimation">@anim/activity_open_enter</item>
            <item name="android:taskOpenExitAnimation">@anim/activity_open_exit</item>
            <item name="android:taskCloseEnterAnimation">@anim/activity_close_enter</item>
            <item name="android:taskCloseExitAnimation">@anim/activity_close_exit</item>
        </style>
    
    

    ActivityOptions

    最后我们再来说下这个ActivityOptions。之所以放在最后说,是因为前两种比较相似,而ActivityOptions可以处理更复杂的效果,可以对过场的View等做操作,实现共享元素等更加炫酷的效果。
    首先,这个ActivityOptions是完全可以替代overridePendingTransition,所以提供了一个类似的方法,接收两个动画资源

    makeCustomAnimation(Context context,int enterResId, int exitResId) 
    

    我们在MainActivity中这样启动Step1Activity

     val intent = Intent(this@MainActivity, Step1Activity::class.java)
     val activityOptions = ActivityOptions.makeCustomAnimation(this,  R.anim.activity_open_enter,  R.anim.activity_open_exit)
     startActivity(intent,activityOptions.toBundle())
    

    这样就实现了跟上面一样的效果,但是我没有找到方法处理finish场景(在共享中倒是可以使用finishAfterTransition回退),如果你知道,欢迎在下方留言。

    下面再说一下ActivityOptions实现共享元素,关于ActivityOptions其他的用法可以去查看官方文档

    ActivityOptions共享元素

    关于什么是共享元素,这个不太好解释,我们直接看例子吧

    图-1 图-2
    共享元素-1.gif 共享元素-2.gif

    图-1的两个不同的Activity上显示logo的ImageView就是共享元素;图-2中的显示logo的View和另一个Activity上的back按钮也是共享元素,相信你已经明白什么叫共享元素了。
    首先在跳转到的Step1Activity布局中为共享元素声明名称

          android:transitionName="transition"
    

    MainActivity跳转用到了ActivityOptions的makeSceneTransitionAnimation方法,参数说明我已经标注在注释上了

        /**
         * @param sharedElement当前Activity中共享元素View
         * @param 跳转至页面共享元素名称
         */
    makeSceneTransitionAnimation(Activity activity,View sharedElement, String sharedElementName)
    

    当有多组共享元素时,还有另外一个方法

    public static ActivityOptions makeSceneTransitionAnimation(Activity activity,Pair<View, String>... sharedElements) 
    

    跳转使用下面的方法

    val intent = Intent(this@MainActivity, Step1Activity::class.java)
    val activityOptions = ActivityOptions.makeSceneTransitionAnimation(
                        this,
                        findViewById<ImageView>(R.id.iv_logo_top),
                        "transition"
                    )
    startActivity(intent, activityOptions.toBundle())
    

    回退时注意需要使用

       finishAfterTransition()
    

    才能在回退时也具有这个共享元素的动画

    总结

    一般我们可以通过theme的方法设置全局的Activity入场出厂动画,然后在一些需要特殊动画的地方使用ActivityOptions或overridePendingTransition处理特殊动画,因为代码中设置的动画的优先级要高,可以覆盖theme中设置的全局动画。

    参考

    Android动画之Activity切换动画overridePendingTransition实现和Theme Xml方式实现
    Android页面切换动画(包括不同任务栈之间页面切换动画)通过Theme去设置

    相关文章

      网友评论

        本文标题:Activity过场动画干货总结

        本文链接:https://www.haomeiwen.com/subject/pxifoctx.html