该文章是一个系列文章,是本人在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. [leetcode]38. Count and Say数数

    The count-and-say sequence is the sequence of integers with the first five terms as following: 1. 1 ...

  2. php 安装gzip

    https://jingyan.baidu.com/article/636f38bb3e538ad6b84610e6.html http://w3cgeek.com/configure-error-p ...

  3. 震惊!90%的程序员不知道的Java知识!

    震惊!90%的程序员不知道的Java知识! 初学Java的时候都会接触的代码 public static void main(String[] args){ ... } 当时就像背公式一样把这行代码给 ...

  4. idea配置网络代理

    背景 公司限制连接外网,很多软件都被限制了,包括idea,只能通过代理上网. 使用代理上网,以往都是在IE的工具-Internet选项-连接里进行设置就OK了,谷歌浏览器啥的就可以上网了.但intel ...

  5. MUI 里js动态添加数字输入框后,增加、减少按钮无效

    numbox 的自动初化是在 mui.ready 时完成的mui 页面默认会自动初始化页面中的所有数字输入框,动态构造的 DOM 需要进行手动初始化.比如:您动态创建了一个 ID 为 abc 的数字输 ...

  6. Instruments Time Profiler时,无法定位代码,如何破?

    都是地址符号,往深里也一直是地址符号,根本没法判断是哪些代码的执行时间 解决办法: 选下面的.

  7. 连接SSH服务器的脚本,自动发送用户名和密码

    利用expect 自动输入用户名和密码 脚本如下 #!/usr/bin/expect # connect ssh server set timeout 30 spawn ssh -l user_nam ...

  8. 大比速:remoting、WCF(http)、WCF(tcp)、WCF(RESTful)、asp.net core(RESTful)

    近来在考虑一个服务选型,dotnet提供了众多的远程服务形式.在只考虑dotnet到dotnet的情形下,我们可以选择remoting.WCF(http).WCF(tcp).WCF(RESTful). ...

  9. 9.indicate、xutils、json

    json数据  页签详情页数据   public class TabData { public int retcode; public TabDetail data;//不是数组的话类型就是这个 pu ...

  10. web API简介(一):API,Ajax和Fetch

    概述 今天逛MDN,无意中看到了web API简介,觉得挺有意思的,就认真读了一下. 下面是我在读的时候对感兴趣的东西的总结,供自己开发时参考,相信对其他人也有用. 什么是API API (Appli ...