Android开发之漫漫长途 XVII——动画
该文章是一个系列文章,是本人在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%"/>
- android:fromXDelta="X",X>0 表示以View动画的开始位置是以当前View的原点向右偏移X个位置,同理,X<0时View动画的开始位置是以当前View的原点向左偏移X个位置
- android:fromXDelta="X%",X>0 表示以View动画的开始位置是以当前View的原点向右偏移View宽度的X%(View.width*X%)个位置,同理,X<0时View动画的开始位置是以当前View的原点向左偏移向右偏移View宽度的X%(View.width*X%)个位置
- 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——动画的更多相关文章
- Android开发之漫漫长途 XVII——动画(续)
该文章是一个系列文章,是本人在Android开发的漫漫长途上的一点感想和记录,我会尽量按照先易后难的顺序进行编写该系列.该系列引用了<Android开发艺术探索>以及<深入理解And ...
- Android开发之漫漫长途 XIV——RecyclerView
该文章是一个系列文章,是本人在Android开发的漫漫长途上的一点感想和记录,我会尽量按照先易后难的顺序进行编写该系列.该系列引用了<Android开发艺术探索>以及<深入理解And ...
- Android开发之漫漫长途 XV——RecyclerView
该文章是一个系列文章,是本人在Android开发的漫漫长途上的一点感想和记录,我会尽量按照先易后难的顺序进行编写该系列.该系列引用了<Android开发艺术探索>以及<深入理解And ...
- Android开发之漫漫长途 Ⅰ——Android系统的创世之初以及Activity的生命周期
该文章是一个系列文章,是本人在Android开发的漫漫长途上的一点感想和记录,我会尽量按照先易后难的顺序进行编写该系列.该系列引用了<Android开发艺术探索>中的相关知识,再次表示该书 ...
- Android开发之漫漫长途 Ⅱ——Activity的显示之Window和View(2)
该文章是一个系列文章,是本人在Android开发的漫漫长途上的一点感想和记录,我会尽量按照先易后难的顺序进行编写该系列.该系列引用了<Android开发艺术探索>以及<深入理解And ...
- Android开发之漫漫长途 Ⅱ——Activity的显示之Window和View(1)
该文章是一个系列文章,是本人在Android开发的漫漫长途上的一点感想和记录,我会尽量按照先易后难的顺序进行编写该系列.该系列引用了<Android开发艺术探索>以及<深入理解And ...
- Android开发之漫漫长途 Ⅳ——Activity的显示之ViewRootImpl初探
该文章是一个系列文章,是本人在Android开发的漫漫长途上的一点感想和记录,我会尽量按照先易后难的顺序进行编写该系列.该系列引用了<Android开发艺术探索>以及<深入理解And ...
- Android开发之漫漫长途 Ⅴ——Activity的显示之ViewRootImpl的PreMeasure、WindowLayout、EndMeasure、Layout、Draw
该文章是一个系列文章,是本人在Android开发的漫漫长途上的一点感想和记录,我会尽量按照先易后难的顺序进行编写该系列.该系列引用了<Android开发艺术探索>以及<深入理解And ...
- Android开发之漫漫长途 番外篇——自定义View的各种姿势1
该文章是一个系列文章,是本人在Android开发的漫漫长途上的一点感想和记录,我会尽量按照先易后难的顺序进行编写该系列.该系列引用了<Android开发艺术探索>以及<深入理解And ...
随机推荐
- [leetcode]53. Maximum Subarray最大子数组和
Given an integer array nums, find the contiguous subarray (containing at least one number) which has ...
- init.d目录下的文件定义
init.d目录下存放的一些脚本一般是linux系统设定的一些服务的启动脚本. 系统在安装时装了好多服务,这里面就有很多对应的脚本. 执行这些脚本可以用来启动,停止,重启这些服务. 1.这些链接文件前 ...
- JavaSE基础知识(5)—面向对象(5.1类和对象概念、创建及内存分配)
一.类和对象的相关概念 1.面向对象和面向过程的理解 面向对象和面向过程都属于解决问题的思考方式.面向过程:以执行者的角度思考问题,侧重于“怎么做”,比较适合解决小型项目面向对象:以指挥者的角度思考问 ...
- js 库
plupload.full.min.js 前端上传利器 jQuery WeUI - V1.0.1 微信公众号开发利器
- 粒子动画——Pygame
你是否也想做出下图这么漂亮的动态效果?想的话就跟着我一起做吧=.= 工具: Python--Pygame 仔细观察上图,你能发现哪些机制呢?再在下面对比一下是否跟你想的一样. 运行机制: 1.随机方向 ...
- centos 安装解压工作
解压工具: yum install ark 编辑器: yum install gedit
- Spring遇到的问题合集
2018-09-15 元素 "tx:annotation-driven" 的前缀 "tx" 未绑定. 后来我加了 http://www.springframew ...
- linux命令重定向>、>>、 1>、 2>、 1>>、 2>>、 <
重定向命令其实用得不少吧,只是重来都没有仔细看过,这波正好又用到 又有空总结一波. 先看>和>>: 他们俩其实唯一的区别就是>是重定向到一个文件,>>是追加内容到文 ...
- springmvc 对日期的转换与处理
一,背景 近期项目上需求还没有确定,难道清闲,对项目中不合理的地方进行一些升级改造.鉴于项目使用的技术框架比较老旧(spring 3.0+) ,一直没有对此做大的升级改造.由于之前项目入参,出参都是使 ...
- 32 bit 与 64 bit 程序(1)如何识别?
一, 怎样判断一个exe可执行程序是32位的还是64位的? 简单的方法: 一般来说在64位的windows7下,打开任务管理器可以知道哪些程序是32位的哪些是64位的,但是因为自己的电脑是64位的wi ...