该文章是一个系列文章,是本人在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. mybatis的基础Dao

    话不多说,直接贴代码吧,因为很多博客都需要用到这个基础dao,怕大家不好查询. 这个基类主要是使用了泛型,这样我就不必为每一个实体都写一个dao,大大节省了时间.其中sqlSessionTemplat ...

  2. sed原理及使用

    前言 环境:centos6.5 sed版本:GNU sed version 4.2.1 本文的代码都是在这个环境下验证的. 一.简介 sed(Stream Editor)意为流编辑器,是Unix常见的 ...

  3. mysql 的 select into 带来的错误数据问题

    在写存储过程的时候,会有一个被忽视的问题: 比如 select user_name into @user_name from user where id = 1; 会出现 其实没有 id =1 这条数 ...

  4. ubuntu中给python3安装opencv

    一.安装相关工具包******注意:以下3,4,5,6为可选项,根据需求安装******1.更新库 sudo apt-get update sudo apt-get upgrade 2.安装从源码构建 ...

  5. C语言基础课第二次作业

    一.  题目7-1 统计学生成绩 1.实验代码 #include<stdio.h> int main(void) { int i,grade,n; ,b=,c=,d=,e=; scanf( ...

  6. php 将对象转化为数组

    $list = json_decode(json_encode($list), true);  

  7. 获得文件的CRC32值

    使用方法:先调用init_crc32_tab生成查询表,再调用calc_img_crc获得文件的CRC值. #define Poly 0xEDB88320L//CRC32标准 ];//CRC查询表 / ...

  8. C++ MFC棋牌类小游戏day2

    反思了一下昨天的设计,觉得略有不足,我决定把棋盘做成单例模式.这样的话需要重新设计棋盘类,emmm,是新建棋盘类. Baord类 成员变量: Location  coordinate;//棋子坐标 b ...

  9. python闭包的详细解析

    一.什么是闭包? 如果一个内嵌函数访问外部嵌套函数作用域的变量,并返回这个函数,则这个函数就是闭包 闭包必须满足三个条件: 1. 必须有一个内嵌函数    2. 内嵌函数必须引用外部嵌套函数中的变量  ...

  10. Mybatis关系映射

    一.一对一关系映射 使用resultType+包装类实现 1.假设问题背景是要求在某一个购物平台的后台程序中添加一个这样的功能:查询某个订单的信息和下该订单的用户信息.首先我们可以知道,一般这样的平台 ...