认识动画(6)常用的几种动画

前言

前篇我们已经介绍了很多基础动画知识,ViewAnimation , PropertyAnimator , 以及插值器和组合动画等等等等,这篇文章我们将会介绍一些在UI设计中,常用的几个动画用例.

动画

LayoutTransition

LayoutTransition(布局过渡效果)是Material design的重要方面,是因为它帮助用户理解app的操作流程,在用户切换视图的时候把不同组件间有机的结合起来.
官方解释:
当在ViewGroup容器中视图层次发生改变时,layoutTransition能够自动的设置过度的动画,在视图容器中为了能够转换,我们通过创建一个ViewGroup对象调用setLayoutTransition(LayoutTransition)在ViewGroup设置这个过渡动画,我们也可以在视图添加和删除时通过setAnimator()来设置动画.
接下来让我们看一下layoutTransition的使用

 LayoutTransition transition = new LayoutTransition();//创建LayoutTransition的对象。
        transition.setDuration(3000);//设置添加过度动画显示的时间。
        transition.setAnimator(LayoutTransition.APPEARING, AnimatorInflater.loadAnimator(this, R.animator.animator));//添加动画
        mGridLayout.setLayoutTransition(transition);//将LayoutTransition添加到ViewGroup容器中。

其中setAnimator(LayoutTransition.APPEARING, AnimatorInflater.loadAnimator(this, R.animator.animator))代表ViewGroup在有元素添加是,该元素的动画效果.第一个参数就是代表当添加新元素时.除此之外还有其他可以选择其他参数:

  • APPEARING:当一个View在ViewGroup中出现时,对次View设置的动画
  • CHANGE_APPEARING:当一个View在ViewGroup中出现时,对此View对其他View位置造成影响,对其他View设置的动画.
  • DISAPPEARING:当一个View在ViewGroup中消失时,对此view设置的动画
  • CHANGE_DISAPPEARING:当一个View在ViewGroup中出消失时,对次View对其他View位置造成影响,对其他View设置的动画.
  • CHANGE:不是由于View出现或消失造成对其他View位置造成影响,然后对其他View设置的动画.

LayoutAnimation

LayoutAnimation是API Level 1 就已经有了,LayoutAnimation是对于viewGroup控件的所有的child view的操作,也就是说它是用来控制ViewGroup中所有的child view来显示的动画,LayoutAnimation动画可以直接在xml中定义:

<layoutAnimation xmlns:android="http://schemas.android.com/apk/res/android"  
    android:delay="30%"  
    android:animationOrder="reverse"  
    android:animation="@anim/slide_right"/>  
  
1. android:delay表示动画播放的延时,既可以是百分比,也可以是float小数。  
2. android:animationOrder表示动画的播放顺序,有三个取值normal(顺序)、reverse(反序)、random(随机)。  
3. android:animation指向了子控件所要播放的动画。 

可以通过下面两种方式加载:

  1. 直接在ViewGroup的layout xml文件中设置:
android:layoutAnimation="@anim/customer_anim"
  1. 在代码中加载:
Animation animation=AnimationUtils.loadAnimation(this, R.anim.slide_right);   //得到一个LayoutAnimationController对象;  
LayoutAnimationController controller = new LayoutAnimationController(animation);   //设置控件显示的顺序;  
controller.setOrder(LayoutAnimationController.ORDER_REVERSE);   //设置控件显示间隔时间;  
controller.setDelay(0.3);   //为ListView设置LayoutAnimationController属性;  
listView.setLayoutAnimation(controller);  
listView.startLayoutAnimation();  

Activity Transtition

Activitry Transition 为应用中的切换页面时,提供了非常优雅的视觉切换效果.我们可以为进入,退出,转换,页面之间的元素共享指定特定的动画.

页面过渡Transition

Mater Design为应用中的切换页面时,提供了非常优雅的视觉切换效果.您可为进入,退出,页面之间的共享元素转换设置特定的动画.
1. Transition动画都包含那些?
Android5.0(API级别 21)支持进入与退出转换的有三个:

Explode Slide Fade
从中心移入或移出 从边缘移入或移出 调整透明度产生渐变

这三个类都继承于Transition,所有有一些属性都是共同的.
常用属性如下:

/ 设置动画的时间。类型:long
transition.setDuration();
// 设置修饰动画,定义动画的变化率,具体设置往下翻就看到了
transition.setInterpolator();
// 设置动画开始时间,延迟n毫秒播放。类型:long
transition.setStartDelay();
// 设置动画的运行路径
transition.setPathMotion();
// 改变动画 出现/消失 的模式。Visibility.MODE_IN:进入;Visibility.MODE_OUT:退出。
transition.setMode();

// 设置动画的监听事件
transition.addListener()
  1. 定义方式
    在java代码中定义:
Explode transition = new Explode();
transition.setDuration(500);
transition.setInterpolator(new AccelerateInterpolator());

在Xml资源定义:

    android:duration="@integer/anim_duration_long"
  android:interpolator="@android:interpolator/bounce"
    />

关于Interpolator不熟悉的请浏览前篇.

  1. 设置Transition时机
    到底该什么时候呢,设置什么样的过渡呢?
    以下为动画的设置场景:
    首页打开页面A:
    页面A->enter首次进入

从A打开B:
页面A->Exit退出
页面B->Enter首次进入

从B返回A:
页面B->Return 返回
页面A->Reenter重新进入
可设置的方法如下:

android:windowContentTransitions                允许使用transitions

android:windowAllowEnterTransitionOverlap       是否覆盖执行,其实可以理解成前后两个页面是同步执行还是顺序执行

android:windowAllowReturnTransitionOverlap      与上面相同。即上一个设置了退出动画,这个设置了进入动画,两者是否同时执行。

android:windowContentTransitionManager          引用TransitionManager XML资源,定义不同窗口内容之间的所需转换。



android:windowEnterTransition                   首次进入显示的动画

android:windowExitTransition                    启动新 Activity ,此页面退出的动画

android:windowReenterTransition                 重新进入的动画。即第二次进入,可以和首次进入不一样。

android:windowReturnTransition                  调用 finishAfterTransition() 退出时,此页面退出的动画



android:windowSharedElementsUseOverlay          指示共享元素在转换期间是否应使用叠加层。

android:windowSharedElementEnterTransition      首次进入显示的动画

android:windowSharedElementExitTransition       启动新 Activity ,此页面退出的动画

android:windowSharedElementReenterTransition    重新进入的动画。即第二次进入,可以和首次进入不一样。

android:windowSharedElementReturnTransition     调用 finishAfterTransition() 退出时,此页面退出的动画

以上为在style中设置属性,也可以在在代码中设置为:

 getWindow().setEnterTransition(visibility);
 // 其余的都是类似
  1. 跳转页面
    至此,用以上知识基本可以设置出绝大多数的过渡效果.然后,跳转页面跟普通的跳转也有点不一样.
    跳转页面
protected void transitionTo(Intent i) {
    ActivityOptionsCompat transitionActivityOptions = ActivityOptionsCompat.makeSceneTransitionAnimation(this);
    startActivity(i, transitionActivityOptions.toBundle());
}

**
退出页面

private void closeActivity(){
    // 如果定义了 return transition ,将使用 定义的动画过渡
    Visibility returnTransition = buildReturnTransition();
    getWindow().setReturnTransition(returnTransition);

    // 如果没有 return transition 被定义,将使用 反进入 的动画
    finishAfterTransition();
}

注意退出时一定要调用:finishAfterTransition();
通过以上设置,就能够完成一个基本的过渡效果了.

  1. Shared Elements Transition共享元素
    共享元素和各种设置与普通的Transition差不多,我们来看看不同的地方
    需要携带共享的View进行跳转
    也就是在跳转的参数中,增加了要共享的View控件
    代码如下:
protected void transitionTo(Intent i) {
    ActivityOptions options = ActivityOptions.makeSceneTransitionAnimation(this,
                                                    Pair.create(view1, "agreedName1"),
                                                    Pair.create(view2, "agreedName2"));
    startActivity(i, options.toBundle());
}

增加的参数的介绍:

Pair.create(
   View view,      // 本页面要共享的 View
   String resId    // 共享控件的transitionName属性
)

注意共享的控件必须有同样的transitionName属性

  1. 页面改变时,动画的效果设置
    changeBounds - 改变目标视图的布局边界
    changeClipBounds - 裁剪目标视图边界
    changeTransform - 改变目标视图的缩放比例和旋转角度
    changeImageTransform-改变目标图片的大小和缩放比例
    设置代码:
Slide slide = new Slide();
slide.setDuration(500);

ChangeBounds changeBounds = new ChangeBounds();
changeBounds.setDuration(500);

getWindow().setEnterTransition(slide);
getWindow().setSharedElementEnterTransition(changeBounds);
  1. TransitionManager控制动画
    这个框架可以让一些复杂的动画特别简单实现



    简单说明一下步骤:

  1. 定义需要切换layout xml页面;
  2. 调用Scence.getSceneForLayout()保存每个Layout;
  3. 调用了TransitionManager.go(scene1, new ChangeBounds())切换.
    相当于定义了不同的xml布局,然后通过简单的调用,就完成了复杂的动画.
    代码如下:
private void setupLayout() {
    scene0 = Scene.getSceneForLayout(binding.sceneRoot, R.layout.activity_animations_scene0, this);
    scene1 = Scene.getSceneForLayout(binding.sceneRoot, R.layout.activity_animations_scene1, this);
    scene2 = Scene.getSceneForLayout(binding.sceneRoot, R.layout.activity_animations_scene2, this);
    scene3 = Scene.getSceneForLayout(binding.sceneRoot, R.layout.activity_animations_scene3, this);
    scene4 = Scene.getSceneForLayout(binding.sceneRoot, R.layout.activity_animations_scene4, this);
    binding.sample3Button1.setOnClickListener(this);
    binding.sample3Button2.setOnClickListener(this);
    binding.sample3Button3.setOnClickListener(this);
    binding.sample3Button4.setOnClickListener(this);
}

@Override
public void onClick(View v) {
    switch (v.getId()) {
        case R.id.sample3_button1:
            TransitionManager.go(scene1, new ChangeBounds());
            break;
        case R.id.sample3_button2:
            TransitionManager.go(scene2, TransitionInflater.from(this).inflateTransition(R.transition.slide_and_changebounds));
            break;
        case R.id.sample3_button3:
            TransitionManager.go(scene3,TransitionInflater.from(this).inflateTransition(R.transition.slide_and_changebounds_sequential));
            break;
        case R.id.sample3_button4:
            TransitionManager.go(scene3,TransitionInflater.from(this).inflateTransition(R.transition.slide_and_changebounds_sequential_with_interpolators));
            break;
    }
}

只需要定义布局,调用调转,
就实现了,点击四个 Button ,分别切换四个布局。
TransitionManager.go() 中可以设置各种动画。

Touch Feedback触摸反馈

在Android L5.0中加入了触摸反馈动画
其中最明显,最具代表性的就是波纹动画,比如点击按钮或者条目时,会从点击的位置产生类似于波纹的效果.

  1. 波纹效果(Ripple)
    当你使用了Material主题后,波纹动画会自动应用在所在控件上,我们当然可以来设置其属性来调整到我们需要的效果.
    可以通过如下代码设置波纹的背景:
  • android:background="?android:attr/selectableItemBackground" 波纹有边界

android:background="android:attr/selectableItemBackgroundBorderless" 波纹超出边界
使用效果如下:

  • B1是不设任何背景的按钮
  • B2设置了?android:attr/selectableItemBackground
  • B3设置了?android:attr/selectableItemBackgroundBorderless
    [图片上传失败...(image-60cc54-1521107181030)]
    )
    设置颜色
    我们也可以通过xml属性来调节动画颜色,从而可以适应不同的主题:
    android:colorControlHighlight:设置波纹颜色
    android:coloeAccent:设置checkbox等控件选中后的颜色

Cricular Reveal圆形揭示

ViewAnimationUtils.creatCircularReveal()当显示或隐藏一组UI时,CircularReveal可为用户提供视觉连续性.



参数说明:

Animator createCircularReveal (View view, // 将要变化的 View
            int centerX,                  // 动画圆的中心的x坐标
            int centerY,                  // 动画圆的中心的y坐标
            float startRadius,            // 动画圆的起始半径
            float endRadius               // 动画圆的结束半径
)

显示View:

private void animShow() {
    View myView = findViewById(R.id.my_view);
    // 从 View 的中心开始
    int cx = (myView.getLeft() + myView.getRight()) / 2;
    int cy = (myView.getTop() + myView.getBottom()) / 2;
    int finalRadius = Math.max(myView.getWidth(), myView.getHeight());

    //为此视图创建动画设计(起始半径为零)
    Animator anim = ViewAnimationUtils.createCircularReveal(myView, cx, cy, 0, finalRadius);
    // 使视图可见并启动动画
    myView.setVisibility(View.VISIBLE);
    anim.start();
}

隐藏View:

private void animHide() {
    final View myView = findViewById(R.id.my_view);
    int cx = (myView.getLeft() + myView.getRight()) / 2;
    int cy = (myView.getTop() + myView.getBottom()) / 2;

    int initialRadius = myView.getWidth();

    // 半径 从 viewWidth -> 0
    Animator anim = ViewAnimationUtils.createCircularReveal(myView, cx, cy, initialRadius, 0);

    anim.addListener(new AnimatorListenerAdapter() {
        @Override
        public void onAnimationEnd(Animator animation) {
            super.onAnimationEnd(animation);
            myView.setVisibility(View.INVISIBLE);
        }
    });
    anim.start();
}

View state changes View状态改变

View state changes设置很简单,就是利用selector标签定义一个xml文件,使得view在状态改变时做出动画.

  1. 定义一个xml文件资源selector
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:state_pressed="true">
        <set>
            <objectAnimator android:duration="@android:integer/config_shortAnimTime"
                            android:propertyName="rotationX"
                            android:valueTo="30"
                            android:valueType="floatType"/>
        </set>
    </item>
    <item android:state_pressed="false">
        <set>
            <objectAnimator android:duration="@android:integer/config_shortAnimTime"
                            android:propertyName="rotationX"
                            android:valueTo="0"
                            android:valueType="floatType"/>
        </set>
    </item>
</selector>

2. 使用方法

  • 布局:android:stateListAnimator属性将其分配给视图
  • 代码:使用AniamtionInflater.loadStateListAnimator()方法读取,并且通过View.setStateListAnimator()方法分配动画到你的视图上
    注意:
    在代码使用的时候要让试图具有onClick功能.

Animate Vector Drawables可动画的矢量图

概述:

Vector(矢量图)对比Bitmap(位图)
绘制效率:Vector依赖于CPU计算,适合图像简单的情况.Bitmap可借助与GPU加速,适合图像复杂的情况
适用情况:Vector适用于ICON,Button,ImageView的小图片,或者需要动画效果时,Bitmap由于在GPU中有缓存功能,所以Bitmap不能做频繁的重绘.
加载速度:SVG快于PNG,但PNG有硬件加速,平均下来加载速度的提升弥补了绘制的速度缺陷.
VectorDrawable,矢量图动画.使用需要添加兼容库,在app的build.gradle文件相关节点下添加:


image.png

1. 静态的VectorDrawable
像在ImageView,ImageButton这样的控件中使用是非常简单的:

<!-- 注意:这里用的是srcCompat -->
app:srcCompat="@drawable/vector_image"

如果要在Button这种带点击效果的控件中使用,则需要通过selector来进行设置,并在对应的Activity中开启下面的设置:

static {
    AppCompatDelegate
        .setCompatVectorFromResourcesEnabled(true);
}

2.使用动态的VectorDrawable
这里需要结合属性动画来实现VectorDrawable效果:
1)创建VectorDrawable文件arrow.xml
[图片上传失败...(image-4eeed1-1521107181030)]
Android Studio的Preview窗口显示的效果如下:
[图片上传失败...(image-b2bbf5-1521107181030)]
2)为VectorDrwable创建属性动画
anim_left.xml



)
anim_right.xml


image.png

3)下来使用动画粘合剂animated-vector(arrow_anim.xml),让属性动画作用于VectorDrawable:


image.png

4)粘合到一起以后,我们就可以在Activity的Layout文件中引用了:


image.png

5)在Activity中添加点击事件anim:


image.png

6)至此编写完毕


image.png
  1. SVG和Vector
    SVG是一套语法规范,在前端中使用.Vector只实现了SVG语法的Path()标签(为了提高解析效率),在Android中使用.
    Vector的语法通过字母和数字的组合来描述一个路径,不同字母表示不同含义,例如:
    M = moveto(M X,Y):讲画笔移动到指定的坐标位置
    L = lineto(L X,Y):画直线到指定坐标
    Z = closepath():关闭路径
    Vector还提供了一些封装好的方法:
    H = horizontal lineto(H X):画水平线到指定的X坐标位置
    V = vertical lineto(V Y):画垂直线到指定的Y坐标的位置
    这里只是介绍了用法,详细例子请参考http://www.10tiao.com/html/169/201702/2650822147/1.html

文章参考:
http://www.10tiao.com/html/169/201702/2650822147/1.html
https://www.jianshu.com/p/37ecb68c5ca1
https://www.jianshu.com/p/a43daa1e3d6e

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

推荐阅读更多精彩内容