Android 5.0 过渡动画

简介

android 5.0之后推出了Material Design(设计材料),不单从UI上带来了更好的视觉美感和用户体验,其中Activity Transition是Material Design中提供的一种动画效果。它通过运动和切换不同状态之间的元素来产生各种动画效果。

transition动画实现的前提条件:minSdkVersion 21

启动方式

5.0版本以下,一般通过两种方式来实现界面的切换动画。

1.配置Activity的主题,style中的windowEnterAnimation和windowExitAnimation设置动画。

2.调用overridePendingTransition(enterAnim,exitAnim)方法,但使用该方法的坑比较多。
如果android系统在2.0以上,手机动画效果已开启,用此方法仍然没有看到效果,注意以下几点:

a.在startActivity(intent)之后使用时,enterAnim在exitAnim上层(图层的上一层)执行(即进入的动画在上层),此时可以没有exitAnim,但是一定要有enterAnim

如果enterAnim传0或者无效的动画资源的话,进入时没有动画效果,新页面会在一瞬间覆盖屏幕,所以exitAnim不会被看见,即使它执行了,你也丝毫看不见。

b.在finish()之后使用时,enterAnim在exitAnim下层执行(出去的动画在上层),此时可以没有enterAnim,但是一定要有exitAnim

道理同上。否则的话,要么动画很丑(页面突然消失,闪黑),要么下层执行的动画被挡住看不见,感觉不到动画效果。

c.参数最好不要传0

这样的话对应的动画页面会一下子消失,背景黑乎乎一片,没有丝毫美感,用一个R.anim.none代替吧,如下:

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

d.两个动画的执行时间最好一致,这样动画步调相同,看起来比较和谐。

5.0版本以上,Activity Transition提供了更加完美的界面切换动画,在需要跳转的场景中,通过调用startActivity(intent,options)(API16以上使用),参数Bundle options是对Activity如何启动的额外操作,该参数一般通过activityOptions.toBunble()来获取。(注意如果调用startActivity(intent)实现跳转,5.0以上设置的transition动画是不起作用的)

ActivityOptions是一个帮助获取Bundle(Activity启动额外操作)的类,内部提供了丰富的api

a

其中常用的三种API:

// 普通Transition启动Activity
startActivity(intent, ActivityOptions.makeSceneTransitionAnimation(this).toBundle());

// 单个共享的View
ActivityOptions options = ActivityOptions.makeSceneTransitionAnimation(this, shareView, "shareName");   

// 多个共享的View     Pair是可变长参数,可通过构造函数或Pair.Create(view,shareName)来指定view和transitionName
ActivityOptions options = ActivityOptions.makeSceneTransitionAnimation(this,  
        Pair.create(view1, "shareName1"),  
        Pair.create(view2, "shareName2"));

如果不想使用transition可以设置options bundle为null。当需要结束当前Activity并回退这个动画时调用Activity.finishAfterTransition()方法。

类型

Activity的动画主要是指Enter(进入)Exit(退出)时实现的动画效果。常见的是从右向左滑进,从左向右滑出。
如上所述可通过配置style主题或是overridePendingTransition(enterAnim,exitAnim)来实现。

5.0开始定义了另外的两种类型:

ReturnTransition & ReenterTransition

Return and Reenter Transitions are the reverse animations for Enter and Exit respectively.

这四种类型的区别:

  • setExitTransition() - 当A start B时,使A中的View退出场景的transition

  • setEnterTransition() - 当A start B时,使B中的View进入场景的transition

  • setReturnTransition() - 当B 返回 A时,使B中的View退出场景的transition

  • setReenterTransition() - 当B 返回 A时,使A中的View进入场景的transition

a
a

那么,5.0的特别的是我们可以在Activity的onCreate()中通过如下方式来指定进入或退出的动画

private void setupWindowAnimations() {
    Fade fade = new Fade();
    fade.setDuration(1000);
    getWindow().setEnterTransition(fade); // 进入动画

    Slide slide = new Slide();
    slide.setDuration(1000);
    getWindow().setReturnTransition(slide); // B-->A(A已启动,重返A)时触发 B调用returnTransition() 同时A调用reenterTransition()
}

或是通过TransitionInflater加载xml

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

Slide slide = TransitionInflater.from(this).inflateTransition(R.transition.activity_slide);
getWindow().setExitTransition(slide);

另外也可以在style.xml中设置

<style name="myTheme" parent="android:Theme.Material">  
        <!-- 允许使用transitions -->  
        <item name="android:windowContentTransitions">true</item>  
   
        <!-- 指定进入和退出transitions -->  
        <item name="android:windowEnterTransition">@transition/explode</item>  
        <item name="android:windowExitTransition">@transition/explode</item>  
   
        <!-- 指定shared element transitions -->  
        <item name="android:windowSharedElementEnterTransition">@transition/change_image_transform</item>  
        <item name="android:windowSharedElementExitTransition">@transition/change_image_transform</item>  
</style>

Transition的实现

通过上述的介绍我们认识了如何启动5.0的Activity过渡动画,接下来就是了解Transition的各种动画效果和Target View的关联

普通的Transition的三种方式:

  • explode:从场景的中心移入或移出

  • slide:从场景的边缘移入或移出

  • fade:调整透明度产生渐变效果

如上述的示例代码就是通过xml或创建Slide/Fade/Explode对象指定相关参数来实现动画效果的。

Shared Elements Transition 共享元素转换

a
a

如图ActivityA ActivityB中都存在共同的Item,称之为共享元素,那么当A-->B时,我们就可以给目标Item设置需要的动画效果,即是ActivityA中的Item过渡到ActivityB中的Item。
共享元素实现的效果有:

  • changeBounds - 改变目标视图的布局边界

  • changeClipBounds - 裁剪目标视图边界

  • changeTransform - 改变目标视图的缩放比例和旋转角度

  • changeImageTransform - 改变目标图片的大小和缩放比例

实现步骤:

a) 在目录res下创建transition文件夹存放transition动画资源

transition/changebounds.xml

<?xml version="1.0" encoding="utf-8"?>
<transitionSet xmlns:android="http://schemas.android.com/apk/res/android"
    android:duration="@integer/anim_duration_long"
    android:interpolator="@android:interpolator/decelerate_cubic"
    >
    <changeBounds>
        <!--patternPathMotion android:patternPathData="M0 0 L0 100 L100 0"/-->
        <arcMotion
            android:maximumAngle="90"
            android:minimumHorizontalAngle="90"
            android:minimumVerticalAngle="0" />

    </changeBounds>
</transitionSet>

values/styles.xml

<style name="MaterialAnimations" parent="@style/Theme.AppCompat.Light.NoActionBar">
    ...
    <item name="android:windowContentTransitions">true</item>

    <!-- specify enter and exit transitions -->
    <item name="android:windowEnterTransition">@transition/explode</item>
    <item name="android:windowExitTransition">@transition/explode</item>

    <!-- specify shared element transitions -->
    <item name="android:windowSharedElementEnterTransition">@transition/changebounds</item>
    <item name="android:windowSharedElementExitTransition">@transition/changebounds</item>
    ...
</style>

b) 在layout中声明共享元素

layout/activity_a.xml

<ImageView
    android:id="@+id/small_blue_icon"
    style="@style/MaterialAnimations.Icon.Small"
    android:src="@drawable/circle"
    android:transitionName="@string/blue_name" />

layout/activity_b.xml

<ImageView
    android:id="@+id/big_blue_icon"
    style="@style/MaterialAnimations.Icon.Big"
    android:src="@drawable/circle"
    android:transitionName="@string/blue_name" />

c) 使用 ActivityOptions.makeSceneTransitionAnimation()启动Activity

上述效果也可通过Java代码来实现:此处省略

Target节点通过Id指定需要实现动画的View

<transitionSet xmlns:android="http://schemas.android.com/apk/res/android">
    <slide android:slideEdge="bottom">
        <targets>
            <target android:targetId="@id/cardview"/>
        </targets>
    </slide>

    <fade>
        <targets>
            <target android:excludeId="@android:id/statusBarBackground"/>
            <target android:excludeId="@android:id/navigationBarBackground"/>
            <target android:excludeId="@id/cardview"/>
        </targets>
    </fade>
</transitionSet>

如上,slide动画指定的target是cardview,意思是cardview从bottom滑入,fade动画指定的target有状态栏、导航栏、cardview,都是实现渐变的动画效果

Animate Reveal

CircleReveal实现圆形缩放效果,可突出显示某个部分。也是android5.0引入的效果,和共享元素一样在低版本上(5.0以下)运行会报错( 抛出.createCircularReveal() not found)。

实现方法:
调用ViewAnimationUtils下的createCircularReveal方法,方法返回一个Animator对象,这个Animator可以设置动画响应属性,调用start方法开始播放动画,CircularReveal实际上是一个属性动画,设置和属性动画是一样的。

private Animator animateRevealColorFromCoordinates(int x, int y) {
    float finalRadius = (float) Math.hypot(viewRoot.getWidth(), viewRoot.getHeight());

    Animator anim = ViewAnimationUtils.createCircularReveal(viewRoot, x, y, 0, finalRadius);
    viewRoot.setBackgroundColor(color);
    anim.setInterpolator(new AccelerateDecelerateInterpolator());
    anim.start();
}

参考

实现Android5.0过渡动画兼容库

Material-Animations

Android 中的转场动画及兼容处理

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 214,658评论 6 496
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,482评论 3 389
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 160,213评论 0 350
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,395评论 1 288
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,487评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,523评论 1 293
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,525评论 3 414
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,300评论 0 270
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,753评论 1 307
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,048评论 2 330
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,223评论 1 343
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,905评论 5 338
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,541评论 3 322
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,168评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,417评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,094评论 2 365
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,088评论 2 352

推荐阅读更多精彩内容

  • Android 自定义View的各种姿势1 Activity的显示之ViewRootImpl详解 Activity...
    passiontim阅读 171,980评论 25 707
  • 假设,两个有Activity A和B A启动B: A发生exit动画,B发生enter动画 B返回A:B发生ret...
    i冰点阅读 17,248评论 7 42
  • 前言 早在Android 4.4,Transition 就已经引入,但在5.0才得以真正的实现。而究竟Transi...
    justCode_阅读 1,305评论 2 8
  • 叶儿随风飘,风儿在身旁温柔的缠绕,只有我的泪,没有人知道。慢慢地枯萎,静静地凋零,曾经那是谁?为我而到来。花儿也有...
    棱镜草阅读 338评论 0 0
  • Handler机制整理目录介绍1.关于handler消息机制图2.关于handler基本介绍3.使用handler...
    杨充211阅读 507评论 0 1