该文章是一个系列文章,是本人在Android开发的漫漫长途上的一点感想和记录,我会尽量按照先易后难的顺序进行编写该系列。该系列引用了《Android开发艺术探索》以及《深入理解Android 卷Ⅰ,Ⅱ,Ⅲ》中的相关知识,另外也借鉴了其他的优质博客,在此向各位大神表示感谢,膜拜!!!


前言

该篇博客我们来说说Android动画的那些事。

Android动画简介

Android的动画是一个令人着迷的地方,不过Android的动画可以简单分为3类,View动画,属性动画。下面我们分别介绍。

View动画

 View动画顾名思义其作用对象为View,包含平移、缩放、旋转、透明,这四类变化分别对应着Animation的子类TranlateAnimation、ScaleAnimation、RotateAnimation和AlphaAnimation。虽然有对应的类,不过,在Android动画中,还是建议用XML来定义,其对应的标签如下所示

View动画的XML描述语法的固定格式

<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
android:interpolator="@[package:]anim/interpolator_resource"
android:shareInterpolator=["true"|"false"]>
<translate
android:fromXDelta="float"
android:fromYDelta="float"
android:toXDelta="float"
android:toYDelta="-float"
android:duration="float"
/>
<scale
android:fromXScale="float"
android:fromYScale="float"
android:toXScale="float"
android:toYScale="float"
android:pivotX="float"
android:pivotY="float"
android:duration="float"
/>
<rotate
android:fromDegrees="float"
android:toDegrees="float"
android:pivotX="float"
android:pivotY="float"
android:duration="float"
/>
<alpha
android:fromAlpha="float"
android:toAlpha="float"
android:duration="float"
/>
...
</set>

注:

android:interpolator表示动画集合所采用的插值器,插值器影响动画的速度,默认是@android:anim/accelerate_decelerate_interpolator,即加减速插值器,关于插值器的概念将会在下面介绍

android:shareInterpolator表示集合中的动画和集合共享同一个插值器,如果集合不指定插值器,那么子动画就需要单独指定插值器或者使用默认值。

View动画坐标系

在使用View动画时,就不得不提View的动画坐标体系,如下图,其坐标系是以View的左上角为原点,横向向右为x轴正方向,纵向向下为y轴正方向,在平移中toXDelta为正数表示以原点为参考沿x轴向右移动,为负数时,反之,旋转时正数角度表示顺时针

View动画的主体是View,更准确的说是View的副本(影子),View动画更改的只是显示,其x,y坐标仍然没有改变,响应事件的位置没有改变,也就是说view本身并没有改变。

也因此,不要使用View动画做交互性操作,例如点击。现在View动画已经很少人使用了,不过View动画简单已用,可以用来做一些简单的不需要交互的动画。

View动画属性配置中 %以及%p的含义

我们先来看一段代码

<translate
...
android:fromXDelta="0.0"
android:toXDelta="50.0%p"
android:fromYDelta="0.0"
android:toYDelta="-50.0%p" /> <scale
...
android:pivotX="50.0%"
android:pivotY="100.0%"/>
  1. android:fromXDelta="X",X>0 表示以View动画的开始位置是以当前View的原点向右偏移X个位置,同理,X<0时View动画的开始位置是以当前View的原点向左偏移X个位置
  2. android:fromXDelta="X%",X>0 表示以View动画的开始位置是以当前View的原点向右偏移View宽度的X%(View.width*X%)个位置,同理,X<0时View动画的开始位置是以当前View的原点向左偏移向右偏移View宽度的X%(View.width*X%)个位置
  3. android:fromXDelta="X%p",X>0 表示以View动画的开始位置是以当前View的父View的原点向右偏移父View宽度的X%(View.Parent.width*X%)个位置,同理,X<0时View动画的开始位置是以当前View的父View的原点向左偏移向右偏移父View宽度的X%(View.Parent.width*X%)个位置

自定义View动画

自定义View动画既简单又复杂,简单的是一个新的动画类只需继承Animation类并重写2个方法,代码如下所示

public class CustomAnimation extends Animation {
@Override
public void initialize(int width, int height, int parentWidth, int parentHeight) {
super.initialize(width, height, parentWidth, parentHeight);
} @Override
protected void applyTransformation(float interpolatedTime, Transformation t) {
super.applyTransformation(interpolatedTime, t);
}
}

说他复杂呢,是因为View动画的过程实际上是矩阵变换的过程,这个涉及线性代数的知识。

View动画的特殊应用场景

LayoutAnimation

LayoutAnimation用于ViewGroup,为ViewGroup指定一个动画,这样它的所有子View在出场时都带有指定的动画效果。

<layoutAnimation xmlns:android="http://schemas.android.com/apk/res/android"
android:animation="@anim/bm_anim_bottom_in"
android:animationOrder="normal"
android:delay="0.5" />

android:animation,为子元素指定具体的入场动画,本例中的代码如下

<set xmlns:android="http://schemas.android.com/apk/res/android"
android:duration="500">
<translate
android:fromYDelta="50.0%p"
android:interpolator="@android:anim/accelerate_decelerate_interpolator"
android:toYDelta="0.0" />
<alpha
android:fromAlpha="0.0"
android:interpolator="@android:anim/accelerate_decelerate_interpolator"
android:toAlpha="1.0" />
</set>

android:delay,表示子元素开始动画的延迟,比如子元素的入场时间周期为500ms,那么0.5 表示每个子元素都要延迟500*0.5=250ms后才会开始播放。总体来说就是第一个子元素延迟250ms播放,第二个子元素延迟500ms播放,后面的子元素以此类推。

android:animationOrder,表示子元素动画的顺序,有三种选项:normal,reverse,random,其中normal表示顺序显示,即排在前面的子元素先开始播放入场动画;reverse表示逆向显示,即排在后面的子元素先开始播放入场动画;random则表示随机播放入场动画。

LayoutAnimation的使用

LayoutAnimation的使用比较简单,可直接在ViewGroup内指定android:layoutAnimation属性,如下所属

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/view_group"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layoutAnimation="@anim/bm_layout_anim_item_bottom_in"
android:orientation="vertical"> <TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="1!"
android:textSize="20sp" /> <TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="2!"
android:textSize="20sp" /> <TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="3!"
android:textSize="20sp" /> <TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="4!"
android:textSize="20sp" /> </LinearLayout>

也可以使用代码控制,如下所示

public class MainActivity extends AppCompatActivity {

    @Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//使用AnimationUtils类的静态方法loadAnimation()来加载XML中的动画XML文件
Animation animation = AnimationUtils.loadAnimation(this, R.anim.bm_anim_bottom_in);
ViewGroup viewGroup = findViewById(R.id.view_group);
LayoutAnimationController layoutAnimationController = new LayoutAnimationController(animation);
layoutAnimationController.setDelay(0.5f);
layoutAnimationController.setOrder(LayoutAnimationController.ORDER_NORMAL);
viewGroup.setLayoutAnimation(layoutAnimationController);
}
}

Activity之间的切换动画

Activity有自己的默认切换效果,不过我们也能自己定义Activity的切换效果,主要用到类Activity的一个函数overridePendingTransition(int enterAnim, int exitAnim),参数说明如下

  • enterAnim:表示Activity被打开时所需要的动画资源id

  • exitAnim:表示Activity被暂停时所需要的动画资源id

启动一个Activity时,可按照下面的代码为其添加切换效果

startActivity(new Intent(this,Main2Activity.class));
overridePendingTransition(R.anim.pop_enter_anim,R.anim.pop_exit_anim); @Override
public void finish() {
super.finish();
overridePendingTransition(R.anim.pop_enter_anim,R.anim.pop_exit_anim);
}

需要注意的是overridePendingTransition必须放在startActivity或者finish之后,才有动画效果

插值器与估值器

  TimeInterpolator中文翻译为时间插值器,它的作用是根据时间流逝的百分比来计算出当前属性值改变的百分比。系统预置的有LinearInterpolator(线性插值器:匀速动画)、AccelerateDecelerateInterpolator(加速减速插值器:动画两头慢中间快)和DecelerateInterpolator(减速插值器:动画越来越慢),OvershootInterpolator(抖动动画)等。

  TypeEvaluator,估值器,它的作用是根据当前属性改变的百分比来计算改变后的属性值。系统预置的有IntEvaluator(针对整型属性)和FloatEvaluator(针对浮点型属性),ArgbEvaluator(针对Color属性)

  

View动画的实际实现者Matrix

前面也说过View动画的过程实际上是矩阵变换的过程,Matrix就是操作矩阵变换的类。Matrix是一个3*3的矩阵,默认创建一个Matrix的对象的时候该矩阵是一个单位矩阵。

if (mMatrix == null) {
mMatrix = new Matrix();//新建对象时默认矩阵是一个3*3的单位矩阵
} else {
mMatrix.reset();//reset方法将该矩阵重置为一个3*3的单位矩阵
}

默认的单位矩阵如下图,

那么这个单位矩阵表示什么意思呢,我们再来看下图。



上面的数值与下面的属性一一对应,

MSCALE_X|Y对应的是缩放变化,

MTRANS_X|Y对应的是平移变化,

MSKEW_X|Y对应的是错切变化

下面我以平移动画为例说明该矩阵如何作用于动画的。我们假设当前View的原点坐标为,那么我们想让该View的原点横向移动,纵向移动

那么用矩阵表示该过程是

这个行列式前面表示变换的矩阵即Matrix,后面的矩阵是我们View的坐标矩阵,也就是说View平移动画的过程是把坐标矩阵点乘一个变换矩阵得到最后的结果矩阵。其他的变化与平移变换类似,更改Matrix矩阵中相关分量即可。


本篇总结

本篇呢,对Android的View动画做了一个比较深入的讲解以及分析,有不到之处还请指出。


下篇预告

下篇呢,继续对Android动画的另外一个大类属性动画作分析


此致,敬礼

Android开发之漫漫长途 XVII——动画的更多相关文章

  1. Android开发之漫漫长途 XVII——动画(续)

    该文章是一个系列文章,是本人在Android开发的漫漫长途上的一点感想和记录,我会尽量按照先易后难的顺序进行编写该系列.该系列引用了<Android开发艺术探索>以及<深入理解And ...

  2. Android开发之漫漫长途 XIV——RecyclerView

    该文章是一个系列文章,是本人在Android开发的漫漫长途上的一点感想和记录,我会尽量按照先易后难的顺序进行编写该系列.该系列引用了<Android开发艺术探索>以及<深入理解And ...

  3. Android开发之漫漫长途 XV——RecyclerView

    该文章是一个系列文章,是本人在Android开发的漫漫长途上的一点感想和记录,我会尽量按照先易后难的顺序进行编写该系列.该系列引用了<Android开发艺术探索>以及<深入理解And ...

  4. Android开发之漫漫长途 Ⅰ——Android系统的创世之初以及Activity的生命周期

    该文章是一个系列文章,是本人在Android开发的漫漫长途上的一点感想和记录,我会尽量按照先易后难的顺序进行编写该系列.该系列引用了<Android开发艺术探索>中的相关知识,再次表示该书 ...

  5. Android开发之漫漫长途 Ⅱ——Activity的显示之Window和View(2)

    该文章是一个系列文章,是本人在Android开发的漫漫长途上的一点感想和记录,我会尽量按照先易后难的顺序进行编写该系列.该系列引用了<Android开发艺术探索>以及<深入理解And ...

  6. Android开发之漫漫长途 Ⅱ——Activity的显示之Window和View(1)

    该文章是一个系列文章,是本人在Android开发的漫漫长途上的一点感想和记录,我会尽量按照先易后难的顺序进行编写该系列.该系列引用了<Android开发艺术探索>以及<深入理解And ...

  7. Android开发之漫漫长途 Ⅳ——Activity的显示之ViewRootImpl初探

    该文章是一个系列文章,是本人在Android开发的漫漫长途上的一点感想和记录,我会尽量按照先易后难的顺序进行编写该系列.该系列引用了<Android开发艺术探索>以及<深入理解And ...

  8. Android开发之漫漫长途 Ⅴ——Activity的显示之ViewRootImpl的PreMeasure、WindowLayout、EndMeasure、Layout、Draw

    该文章是一个系列文章,是本人在Android开发的漫漫长途上的一点感想和记录,我会尽量按照先易后难的顺序进行编写该系列.该系列引用了<Android开发艺术探索>以及<深入理解And ...

  9. Android开发之漫漫长途 番外篇——自定义View的各种姿势1

    该文章是一个系列文章,是本人在Android开发的漫漫长途上的一点感想和记录,我会尽量按照先易后难的顺序进行编写该系列.该系列引用了<Android开发艺术探索>以及<深入理解And ...

随机推荐

  1. C# NPOI 日期格式

    之前整理的NPOI导入导出Excel 在之前使用过程中没发现问题. 但是后来发现导入的文档如果有日期时间格式,导入时会有混乱 后来找了一下解决方案,最终将其中一段修改即可导入日期(导出未测试) 原因 ...

  2. Codeforces Round #436 (Div. 2)C. Bus 模拟

    C. Bus time limit per test: 2 seconds memory limit per test: 256 megabytes input: standard input out ...

  3. Spring Boot 启动(二) Environment 加载

    Spring Boot 启动(二) Environment 加载 Spring 系列目录(https://www.cnblogs.com/binarylei/p/10198698.html) 上一节中 ...

  4. 密码\路径\IP...备忘录

    1.linux 192.168.200.128:22 root/123456

  5. Python中添加中文注释报错SyntaxError: Non-UTF-8 code starting with '\xc1'

    问题:在文本编辑器中编辑Python文件时添加中文注释,运行python文件时报错.SyntaxError: Non-UTF-8 code starting with '\xc1' 解决方法:在文本开 ...

  6. 1-JRE与JDK等知识

  7. 《Linux就该这么学》第九天课程

    这次课程主要学了如何分区以及RAID技术 有扩展分区:扩展分区可以指定sdb*中的*(1~4)为多少,则其他三个为主分区,扩展分区中的逻辑分区sdb*(*从5开始)无扩展分区:四个皆为主分区 RAID ...

  8. OKR 与 KPI

    作者:Cat Chen链接:https://www.zhihu.com/question/22478049/answer/23833548来源:知乎著作权归作者所有.商业转载请联系作者获得授权,非商业 ...

  9. k-th smallest 问题总结

    k-th smallest/biggest 问题大约有这几道: 373. Find K Pairs with Smallest Sums 从两个list里各取一个数求和,求所有可能的sum里第k小的 ...

  10. MD5盐值加密

    加密思路 思路解析:(数据解析过程基于16进制来处理的,加密后为16进制字符串) 加密阶段: 对一个字符串进行MD5加密,我们需要使用到MessageDigest(消息摘要对象),需要一个盐值(sal ...