美文网首页动画
Android动画之场景变换Transition动画的使用

Android动画之场景变换Transition动画的使用

作者: sliencexiu | 来源:发表于2019-08-06 07:47 被阅读0次

    Transition 概述

    Trasition 内部保存了所有关于动画的信息,当场景变换时动画将在目标对象上执行。Transition基于两个概念:场景(scenes)和变换(transitions),场景是UI当前状态,变换则定义了在不同场景之间动画变化的过程。

    Transition分为三种类型(android5.0中使用)。
    进入动画:Activity中的所有视图进入屏幕的动画。
    退出动画:Activity中的所有视图退出屏幕的动画。
    共享元素动画:利用共享的元素实现Activity的跳转动画。
    进入动画和退出动画合称Content Transition(内容变换动画),所以Transition分为内容变换动画和共享元素动画。

    当一个场景改变的时候,transition主要负责:
    捕捉每个View在开始场景和结束场景时的状态,根据两个场景(开始和结束)之间的区别创建一个Animator,所以Transition内部利用了属性动画。

    如何在Activity中使用Transition

    • 在使用Transition 的activity中需要启用transition ,可以通过代码也可以通过设置主题:

    代码方式,在setContentView之前调用:
    getWindow().requestFeature(Window.FEATURE_CONTENT_TRANSITIONS);
    主题xml方式:

    <item name="android:windowContentTransitions">true</item>
    
    • Activity中设置进入,退出Transition动画,Material主题默认会将exit的transition设置成null而enter的transition设置成Fade ,如果reenter 或者 return transition没有明确设置,则将用exit 和enter的transition替代。

    • 开始一个activity的content transition需要调用startActivity(Context, Bundle)方法,Bundle参数生成方法ActivityOptions.makeSceneTransitionAnimation(activity, pairs).toBundle();

    • 在代码中触发通过finishAfterTransition()方法触发返回动画,而不是调用finish()方法。

    Fragment中使用Transition

    和activity中使用大体相同,不同点如下:

    • Fragment在其FragmentTransaction执行added, removed, attached, detached, shown, ,hidden时触发动画。

    • 在Fragment commit之前,共享元素需要通过调用addSharedElement(View, String) 方法来成为FragmentTransaction的一部分。

    2 Content Transition

    content transition决定了非共享view元素在activity和fragment切换期间是如何进入或者退出场景的
    可以利用代码或者XML方式实现。

    设置Content Transition的函数:
    setEnterTransition() - ActivityA 跳转到 ActivityB,ActivityB中的View进入场景的transition。
    setExitTransition() - ActivityA 跳转到 ActivityB,ActivityA中的View退出场景的transition。
    setReturnTransition() - 从ActivityB 返回Activity A时,ActivityB中的View退出场景的transition。
    setReenterTransition() - 从ActivityB 返回Activity A时,ActivityA中的View进入场景的transition

    xml中的属性

    //对应setEnterTransition
    <item name="android:windowEnterTransition"></item>   
    //对应setExitTransition
    <item name="android:windowExitTransition"></item>
    //对应setReturnTransition
    <item name="android:windowReturnTransition"></item>
    //对应setReenterTransition
    <item name="android:windowReenterTransition"></item>
    

    系统提供的动画效果(用于content Transition)
    explode(分解):从屏幕中间进或出,移动视图。
    slide(滑动):从屏幕边缘进或出,移动试图。
    fade(淡出):通过改变屏幕上的视图的不透明度,达到添加或移除视图。

    三种效果都有对应的实现类,分别为:
    分解:Explode
    Xml中定义方式:<explode xmlns:android="http://schemas.android.com/apk/res/android"/>

    滑动:Slide,
    setSlideEdge(int slideEdge) 设置从哪个边出现或隐藏,取值为
    Gravity.LEFT, Gravity.TOP, Gravity.RIGHT, Gravity.BOTTOM, Gravity.START, Gravity.END.
    对应的xml中的属性为android:slideEdge
    Xml中定义slide方式:

    <slide xmlns:android="http://schemas.android.com/apk/res/android" android:slideEdge="bottom"/>
    

    淡入淡出对应Fade:
    Xml中使用方式:<fade xmlns:android="http://schemas.android.com/apk/res/android"/>

    XML方式定义transition

    explode

    <?xml version="1.0" encoding="utf-8"?>
    <transitionSet xmlns:android="http://schemas.android.com/apk/res/android">
    <explode
        android:duration="500"
        android:interpolator="@android:interpolator/accelerate_decelerate"/>
    </transitionSet>
    

    fade

    <?xml version="1.0" encoding="utf-8"?>
    <transitionSet xmlns:android="http://schemas.android.com/apk/res/android">
    <fade
        android:duration="500"
        android:interpolator="@android:interpolator/accelerate_decelerate"/>
    </transitionSet>
    

    slide

    <?xml version="1.0" encoding="utf-8"?>
    <transitionSet xmlns:android="http://schemas.android.com/apk/res/android">
        <slide
            android:duration="500"
            android:slideEdge="bottom"
            android:interpolator="@android:interpolator/accelerate_decelerate" />
    </transitionSet>
    

    xml中实现进入退出动画

    Style中设置:

    <item name="android:windowContentTransitions">true</item>
            <item name="android:windowEnterTransition">@transition/explode</item>
            <item name="android:windowExitTransition">@transition/fade</item>
            <item name="android:windowReenterTransition">@transition/solid</item>
            <item name="android:windowReturnTransition">@transition/explode</item>
    

    调用

    ActivityOptionsCompat activityOptionsCompat = ActivityOptionsCompat.makeSceneTransitionAnimation(Main8Activity.this);
    Intent intent = new Intent(Main8Activity.this, Main7Activity.class);
    startActivity(intent,activityOptionsCompat.toBundle());
    

    退出时调用:

    @Override
    public void onBackPressed() {
        super.onBackPressed();
        ActivityCompat.finishAfterTransition(this);
    }
    

    代码方式实现

    oncreate函数中

    @Override
    protected void onCreate(Bundle savedInstanceState) {
       // overridePendingTransition(R.anim.translate_left_in,0);
        getWindow().requestFeature(Window.FEATURE_CONTENT_TRANSITIONS);
        getWindow().setEnterTransition(new Explode());
        getWindow().setExitTransition(new Fade());
        Transition transition1 =  TransitionInflater.from(Main8Activity.this).inflateTransition(android.R.transition.slide_bottom);
        getWindow().setReenterTransition(transition1);
        Transition transition2 =  TransitionInflater.from(Main8Activity.this).inflateTransition(R.transition.explode);
        getWindow().setReturnTransition(transition2);
        //super.onCreate之前
        super.onCreate(savedInstanceState);
    

    退出时调用:

    @Override
    public void onBackPressed() {
        super.onBackPressed();
        ActivityCompat.finishAfterTransition(this);
    }
    

    explode,fade,solid效果

    explode效果

    getWindow().requestFeature(Window.FEATURE_CONTENT_TRANSITIONS);
    getWindow().setEnterTransition(new Explode());
    getWindow().setExitTransition(new Explode());
    Transition transition1 =  TransitionInflater.from(Main8Activity.this).inflateTransition(android.R.transition.explode);
    getWindow().setReenterTransition(transition1);
    Transition transition2 =  TransitionInflater.from(Main8Activity.this).inflateTransition(R.transition.explode);
    getWindow().setReturnTransition(transition2);
    
    
    图片3

    fade效果

    getWindow().requestFeature(Window.FEATURE_CONTENT_TRANSITIONS);
    getWindow().setEnterTransition(new Fade());
    getWindow().setExitTransition(new Fade());
    Transition transition1 =  TransitionInflater.from(Main8Activity.this).inflateTransition(android.R.transition.fade);
    getWindow().setReenterTransition(transition1);
    Transition transition2 =  TransitionInflater.from(Main8Activity.this).inflateTransition(R.transition.fade);
    getWindow().setReturnTransition(transition2);
    
    图片4

    solid

    getWindow().requestFeature(Window.FEATURE_CONTENT_TRANSITIONS);
    getWindow().setEnterTransition(new Slide(Gravity.BOTTOM));
    getWindow().setExitTransition(new Slide(Gravity.TOP));
    Transition transition1 =  TransitionInflater.from(Main8Activity.this).inflateTransition(R.transition.solid);
    getWindow().setReenterTransition(transition1);
    Transition transition2 =  TransitionInflater.from(Main8Activity.this).inflateTransition(android.R.transition.slide_bottom);
    getWindow().setReturnTransition(transition2);
    
    图片5
    ]
    PS:
    如果从ActivityA启动ActivityB,界面切换的时候,ActivityA退出还没有完全展示exitAnimator时,ActivityB就进入了,如果想等ActivityA完全退出后ActivityB再进入可以通过设置setAllowEnterTransitionOverlap(false)(默认是true),同样可以在xml中设置:
    <item name="android:windowAllowEnterTransitionOverlap">false</item>
    <item name="android:windowAllowReturnTransitionOverlap">false</item>

    3 共享元素动画

    函数说明:
    setSharedElementEnterTransition();ActivityA 跳转到 ActivityB,ActivityB进入动画transitionsetSharedElementExitTransition();ActivityA 跳转到 ActivityB,ActivityA退出动画setSharedElementReenterTransition();从ActivityB 返回Activity A时,ActivityA进入场景的transition。
    setSharedElementReturnTransition();从ActivityB 返回Activity A时,ActivityB退出场景的transition。

    xml中对应的设置

    <item name="android:windowSharedElementEnterTransition"></item>
    <item name="android:windowSharedElementExitTransition"></item>
    <item name="android:windowSharedElementReenterTransition"></item>
    <item name="android:windowSharedElementReturnTransition"></item>
    

    系统提供的自定义动画
    changeBounds:改变目标视图的布局边界,也就是改变view的宽高或者位置。
    changeClipBounds:裁剪目标视图边界,view的裁剪区域边界。
    changeTransform:改变目标的缩放比例和旋转角度,对view进行缩放,旋转操作。
    changeImageTransform:改变目标图片的大小和缩放比例,也就是改变图片的ScaleType。
    overlay:覆盖
    arcMotion:圆弧效果

    对应的类:
    ChangeBounds -捕获共享元素的layout bound,然后播放layout bound变化动画。ChangeBounds 是共享元素变换中用的最多的,因为前后两个activity中共享元素的大小和位置一般都是不同的。
    ChangeTransform - 捕获共享元素的缩放(scale)与旋转(rotation)属性 ,然后播放缩放(scale)与旋转(rotation)属性变化动画。
    ChangeClipBounds - 捕获共享元素clip bounds,然后播放clip bounds变化动画,view的裁剪区域边界。
    ChangeImageTransform - 捕获共享元素(ImageView)的transform matrices 属性,然后播放ImageViewtransform matrices 属性变化动画。与ChangeBounds相结合,这个变换可以让ImageView在动画中高效实现大小,形状或者ImageView.ScaleType 属性平滑过度。

    getWindow().setSharedElementsUseOverlay(true); overlay效果开启

    定义xml文件
    changeBounds

    <?xml version="1.0" encoding="utf-8"?>
    <transitionSet xmlns:android="http://schemas.android.com/apk/res/android">
        <changeBounds
            android:duration="1000"
            android:interpolator="@android:interpolator/accelerate_decelerate" />
    </transitionSet>
    

    changeClipBounds

    <?xml version="1.0" encoding="utf-8"?>
    <transitionSet xmlns:android="http://schemas.android.com/apk/res/android">
        <changeClipBounds
            android:duration="1000"
            android:interpolator="@android:interpolator/accelerate_decelerate" />
    </transitionSet>
    

    changeImageTransform

    <?xml version="1.0" encoding="utf-8"?>
    <transitionSet xmlns:android="http://schemas.android.com/apk/res/android">
        <changeImageTransform
            android:duration="500"
            android:interpolator="@android:interpolator/accelerate_decelerate" />
    </transitionSet>
    

    changeTransform

    <?xml version="1.0" encoding="utf-8"?>
    <transitionSet xmlns:android="http://schemas.android.com/apk/res/android">
        <changeTransform
            android:duration="500"
            android:interpolator="@android:interpolator/accelerate_decelerate" />
    </transitionSet>
    

    style中设置

    <item name="android:windowContentTransitions">true</item>
    <item name="android:windowSharedElementEnterTransition">@transition/changebounds</item>
    <item name="android:windowSharedElementExitTransition">@transition/changeclipbounds</item>
    <item name="android:windowSharedElementReenterTransition">@transition/changeimagetransform</item>
    <item name="android:windowSharedElementReturnTransition">@transition/changetransform</item>
    
     Bundle bundle = ActivityOptionsCompat.makeSceneTransitionAnimation(Main8Activity.this,gongxiang,"shareElement").toBundle();
     Intent intent = new Intent(Main8Activity.this, Main7Activity.class);
     startActivity(intent,bundle);
    
    <ImageView
        android:id="@+id/gongxiang"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="400px"
        android:src="@drawable/image_home_game_nor2"
        android:transitionName="shareElement"/>
    
    <ImageView
        android:id="@+id/toptop"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:src="@drawable/image_home_game_nor"
        android:scaleType="fitCenter"
        android:transitionName="shareElement"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintRight_toRightOf="parent" />
    

    Main8Activity和Main7Activity 共享两个圆形imageView:

    代码实现

    getWindow().requestFeature(Window.FEATURE_CONTENT_TRANSITIONS);
    ChangeBounds changeBounds = new ChangeBounds();
    changeBounds.setDuration(1000);
    ChangeClipBounds changeClipBounds = new ChangeClipBounds();
    changeClipBounds.setDuration(1000);
    ChangeImageTransform changeImageTransform = new ChangeImageTransform();
    changeImageTransform.setDuration(1000);
    ChangeTransform changeTransform = new ChangeTransform();
    changeTransform.setDuration(1000);
    getWindow().setSharedElementEnterTransition(changeBounds);
    getWindow().setSharedElementExitTransition(changeClipBounds);
    getWindow().setSharedElementReenterTransition(changeImageTransform);
    getWindow().setSharedElementReturnTransition(changeTransform);
    

    开启Overlay

    Overlay的具体效果不太明白,但是从语义来说应该是让动画更加的融合自然。
    getWindow().setSharedElementsUseOverlay(true);


    image

    参考:
    http://www.jcodecraeer.com/a/anzhuokaifa/androidkaifa/2015/0201/2394.html

    Animation动画概述和执行原理
    Android动画之补间动画TweenAnimation
    Android动画之逐帧动画FrameAnimation
    Android动画之插值器简介和系统默认插值器
    Android动画之插值器Interpolator自定义
    Android动画之视图动画的缺点和属性动画的引入
    Android动画之ValueAnimator用法和自定义估值器
    Android动画之ObjectAnimator实现补间动画和ObjectAnimator自定义属性
    Android动画之ObjectAnimator中ofXX函数全解析-自定义Property,TypeConverter,TypeEvaluator
    Android动画之AnimatorSet联合动画用法
    Android动画之LayoutTransition布局动画
    Android动画之共享元素动画
    Android动画之ViewPropertyAnimator(专用于view的属性动画)
    Android动画之Activity切换动画overridePendingTransition实现和Theme Xml方式实现
    Android动画之ActivityOptionsCompat概述
    Android动画之场景变换Transition动画的使用
    Android动画之Transition和TransitionManager使用
    Android动画之圆形揭露动画Circular Reveal
    Android 动画之 LayoutAnimation 动画
    Android动画之视图动画的缺点和属性动画的引入

    相关文章

      网友评论

        本文标题:Android动画之场景变换Transition动画的使用

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