Android中的动画详解系列【3】——自定义动画研究
在上一篇中我们使用到了位移动画TranslateAnimation,下面我们先来看看TranslateAnimation是如何实现Animation中的抽象方法的:
/*
* Copyright (C) 2006 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/ package android.view.animation; import android.content.Context;
import android.content.res.TypedArray;
import android.util.AttributeSet; /**
* An animation that controls the position of an object. See the
* {@link android.view.animation full package} description for details and
* sample code.
*
*/
public class TranslateAnimation extends Animation {
private int mFromXType = ABSOLUTE;
private int mToXType = ABSOLUTE; private int mFromYType = ABSOLUTE;
private int mToYType = ABSOLUTE; private float mFromXValue = 0.0f;
private float mToXValue = 0.0f; private float mFromYValue = 0.0f;
private float mToYValue = 0.0f; private float mFromXDelta;
private float mToXDelta;
private float mFromYDelta;
private float mToYDelta; /**
* Constructor used when a TranslateAnimation is loaded from a resource.
*
* @param context Application context to use
* @param attrs Attribute set from which to read values
*/
public TranslateAnimation(Context context, AttributeSet attrs) {
super(context, attrs); TypedArray a = context.obtainStyledAttributes(attrs,
com.android.internal.R.styleable.TranslateAnimation); Description d = Description.parseValue(a.peekValue(
com.android.internal.R.styleable.TranslateAnimation_fromXDelta));
mFromXType = d.type;
mFromXValue = d.value; d = Description.parseValue(a.peekValue(
com.android.internal.R.styleable.TranslateAnimation_toXDelta));
mToXType = d.type;
mToXValue = d.value; d = Description.parseValue(a.peekValue(
com.android.internal.R.styleable.TranslateAnimation_fromYDelta));
mFromYType = d.type;
mFromYValue = d.value; d = Description.parseValue(a.peekValue(
com.android.internal.R.styleable.TranslateAnimation_toYDelta));
mToYType = d.type;
mToYValue = d.value; a.recycle();
} /**
* Constructor to use when building a TranslateAnimation from code
*
* @param fromXDelta Change in X coordinate to apply at the start of the
* animation
* @param toXDelta Change in X coordinate to apply at the end of the
* animation
* @param fromYDelta Change in Y coordinate to apply at the start of the
* animation
* @param toYDelta Change in Y coordinate to apply at the end of the
* animation
*/
public TranslateAnimation(float fromXDelta, float toXDelta, float fromYDelta, float toYDelta) {
mFromXValue = fromXDelta;
mToXValue = toXDelta;
mFromYValue = fromYDelta;
mToYValue = toYDelta; mFromXType = ABSOLUTE;
mToXType = ABSOLUTE;
mFromYType = ABSOLUTE;
mToYType = ABSOLUTE;
} /**
* Constructor to use when building a TranslateAnimation from code
*
* @param fromXType Specifies how fromXValue should be interpreted. One of
* Animation.ABSOLUTE, Animation.RELATIVE_TO_SELF, or
* Animation.RELATIVE_TO_PARENT.
* @param fromXValue Change in X coordinate to apply at the start of the
* animation. This value can either be an absolute number if fromXType
* is ABSOLUTE, or a percentage (where 1.0 is 100%) otherwise.
* @param toXType Specifies how toXValue should be interpreted. One of
* Animation.ABSOLUTE, Animation.RELATIVE_TO_SELF, or
* Animation.RELATIVE_TO_PARENT.
* @param toXValue Change in X coordinate to apply at the end of the
* animation. This value can either be an absolute number if toXType
* is ABSOLUTE, or a percentage (where 1.0 is 100%) otherwise.
* @param fromYType Specifies how fromYValue should be interpreted. One of
* Animation.ABSOLUTE, Animation.RELATIVE_TO_SELF, or
* Animation.RELATIVE_TO_PARENT.
* @param fromYValue Change in Y coordinate to apply at the start of the
* animation. This value can either be an absolute number if fromYType
* is ABSOLUTE, or a percentage (where 1.0 is 100%) otherwise.
* @param toYType Specifies how toYValue should be interpreted. One of
* Animation.ABSOLUTE, Animation.RELATIVE_TO_SELF, or
* Animation.RELATIVE_TO_PARENT.
* @param toYValue Change in Y coordinate to apply at the end of the
* animation. This value can either be an absolute number if toYType
* is ABSOLUTE, or a percentage (where 1.0 is 100%) otherwise.
*/
public TranslateAnimation(int fromXType, float fromXValue, int toXType, float toXValue,
int fromYType, float fromYValue, int toYType, float toYValue) { mFromXValue = fromXValue;
mToXValue = toXValue;
mFromYValue = fromYValue;
mToYValue = toYValue; mFromXType = fromXType;
mToXType = toXType;
mFromYType = fromYType;
mToYType = toYType;
} @Override
protected void applyTransformation(float interpolatedTime, Transformation t) {
float dx = mFromXDelta;
float dy = mFromYDelta;
if (mFromXDelta != mToXDelta) {
dx = mFromXDelta + ((mToXDelta - mFromXDelta) * interpolatedTime);
}
if (mFromYDelta != mToYDelta) {
dy = mFromYDelta + ((mToYDelta - mFromYDelta) * interpolatedTime);
}
t.getMatrix().setTranslate(dx, dy);
} @Override
public void initialize(int width, int height, int parentWidth, int parentHeight) {
super.initialize(width, height, parentWidth, parentHeight);
mFromXDelta = resolveSize(mFromXType, mFromXValue, width, parentWidth);
mToXDelta = resolveSize(mToXType, mToXValue, width, parentWidth);
mFromYDelta = resolveSize(mFromYType, mFromYValue, height, parentHeight);
mToYDelta = resolveSize(mToYType, mToYValue, height, parentHeight);
}
可以看到实际上重写了两个方法:initialize和applyTransformation
/**
* Initialize this animation with the dimensions of the object being
* animated as well as the objects parents. (This is to support animation
* sizes being specifed relative to these dimensions.)
*
* <p>Objects that interpret Animations should call this method when
* the sizes of the object being animated and its parent are known, and
* before calling {@link #getTransformation}.
*
*
* @param width Width of the object being animated
* @param height Height of the object being animated
* @param parentWidth Width of the animated object's parent
* @param parentHeight Height of the animated object's parent
*/
public void initialize(int width, int height, int parentWidth, int parentHeight) {
reset();
mInitialized = true;
}
/**
* Helper for getTransformation. Subclasses should implement this to apply
* their transforms given an interpolation value. Implementations of this
* method should always replace the specified Transformation or document
* they are doing otherwise.
*
* @param interpolatedTime The value of the normalized time (0.0 to 1.0)
* after it has been run through the interpolation function.
* @param t The Transofrmation object to fill in with the current
* transforms.
*/
protected void applyTransformation(float interpolatedTime, Transformation t) {
}
从initialize方法的注释上看,这个方法的主要作用是:初始化对象的尺寸以及父容器尺寸(为了确定和父容器的相对位置)。
从applyTransformation方法的注释上看,这个方法应该被实现,这个方法给出了一个interpolation值,并帮助获得Transformation对象,应该自己设置transformation对象来实现自己的动画效果。
好吧,基于以上研究,我们试着来重写一个Animation
package com.example.testanimation; import android.graphics.Camera;
import android.graphics.Matrix;
import android.view.animation.Animation;
import android.view.animation.LinearInterpolator;
import android.view.animation.Transformation; /**
* 自定义动画
* @author 阳光小强
*
*/
public class MyAnimation extends Animation{ private float centerX;
private float centerY;
private int duration;
private Camera camera = new Camera();
public MyAnimation(float x, float y, int duration){
this.centerX = x;
this.centerY = y;
this.duration = duration;
} @Override
public void initialize(int width, int height, int parentWidth,
int parentHeight) {
super.initialize(width, height, parentWidth, parentHeight); setDuration(duration); setFillAfter(true); setInterpolator(new LinearInterpolator());
} @Override
protected void applyTransformation(float interpolatedTime, Transformation t) {
camera.save();
camera.translate(100f - 100f * interpolatedTime, 150f * interpolatedTime -150, 80f - 80f * interpolatedTime);
camera.rotateY(360 * interpolatedTime);
camera.rotateX(360 * interpolatedTime);
Matrix matrix = t.getMatrix();
camera.getMatrix(matrix);
matrix.preTranslate(-centerX, -centerY);
matrix.postTranslate(centerX, centerY);
camera.restore();
}
}
代码解释:
1、setDuration(duration):设置动画时间
2、setFillAfter(true):设置动画结束后保持,如果设为false则动画结束后回到原来状态。
3、setInterpolator(new LinearInterpolator()):Interpolater实际上是控制补间动画的插入帧的频率的,所以就会有加速、减速、匀速动画。
4、Camera:一个空间变换工具,类似于Matrix,提供了各种变换方法,如上面的translate和rotateY等。
5、Matrix:一个三维的矩阵变换函数。
6、camera.getMatrix(matrix):计算当前的矩阵变换,并将其复制到矩阵matrix中。
7、matrix.preTranslate :执行矩阵指定的转换。
8、matrix.postTranslate:执行矩阵指定的转换(后面两个方法怎么转换,有什么区别,这就是数学知识了,一两句也说不清)。
Android中的动画详解系列【3】——自定义动画研究的更多相关文章
- Android中的动画详解系列【4】——Activity之间切换动画
前面介绍了Android中的逐帧动画和补间动画,并实现了简单的自定义动画,这一篇我们来看看如何将Android中的动画运用到实际开发中的一个场景--Activity之间跳转动画. 一.定义动画资源 如 ...
- Android中Service(服务)详解
http://blog.csdn.net/ryantang03/article/details/7770939 Android中Service(服务)详解 标签: serviceandroidappl ...
- Android中mesure过程详解
我们在编写layout的xml文件时会碰到layout_width和layout_height两个属性,对于这两个属性我们有三种选择:赋值成具体的数值,match_parent或者wrap_conte ...
- Android中Intent组件详解
Intent是不同组件之间相互通讯的纽带,封装了不同组件之间通讯的条件.Intent本身是定义为一个类别(Class),一个Intent对象表达一个目的(Goal)或期望(Expectation),叙 ...
- Android中的动画详解系列【2】——飞舞的蝴蝶
这一篇来使用逐帧动画和补间动画来实现一个小例子,首先我们来看看Android中的补间动画. Android中使用Animation代表抽象的动画类,该类包括下面几个子类: AlphaAnimation ...
- RxJava在Android中使用场景详解
RxJava 系列文章 <一,RxJava create操作符的用法和源码分析> <二,RxJava map操作符用法详解> <三,RxJava flatMap操作符用法 ...
- Android中shape属性详解
一.简单使用 刚开始,就先不讲一堆标签的意义及用法,先简单看看shape标签怎么用. 1.新建shape文件 首先在res/drawable文件夹下,新建一个文件,命名为:shape_radius.x ...
- Android中的Service详解
今天我们就来介绍一下Android中的四大组件中的服务Service,说到Service, 它分为本地服务和远程服务:区分这两种服务就是看客户端和服务端是否在同一个进程中,本地服务是在同一进程中的,远 ...
- Android中Service 使用详解(LocalService + RemoteService)
Service 简介: Service分为本地服务(LocalService)和远程服务(RemoteService): 1.本地服务依附在主进程上而不是独立的进程,这样在一定程度上节约了资源,另外L ...
随机推荐
- Angular:内置指令
[ngIf]表达式结果为真,显示元素:表达式结果为假,移除元素. <div *ngIf="a > b"></div> [ngSwitch]对表达式进行 ...
- HTML高级标签之表格标签
前面学习了一下HTML的经常使用标签, 今天開始高级标签之路! 一.表格标签 1.作用: 创建一张表格 2.各属性作用: <table cellspacing="0" cel ...
- Linux下读写寄存器
arm裸机下读写寄存器很容易,各个寄存器和内存的地址是单一地址空间,他们是用相同的指令进行读写操作的.而在linux下就要复杂很多,因为linux支持多个体系架构的CPU.比如arm和x86就不一样, ...
- 5.Zookeeper的两种安装和配置(Windows):单机模式与集群模式
转自:https://blog.csdn.net/a906998248/article/details/50815031
- Nginx配置GZIP
记录一次解决网站加载慢的问题 一. nginx配置 gzip on;gzip_min_length 1k;gzip_buffers 4 16k;gzip_http_version 1.1;g ...
- GO语言学习(二十)Go 语言递归函数
Go 语言递归函数 递归,就是在运行的过程中调用自己. 语法格式如下: func recursion() { recursion() /* 函数调用自身 */ } func main() { recu ...
- 【例题 6-21 UVA - 506】System Dependencies
[链接] 我是链接,点我呀:) [题意] 在这里输入题意 [题解] 记录每个物品它的依赖有哪些,以及它被哪些东西依赖就可以了. 显式安装的东西不能被隐式删除删掉(就是remove item,然后删除i ...
- Wicket实战(二)hello world
上次的博文Wicket实战(一)概述中给大家简介了一下关于Wicket的概念性内容,今天我们完毕第一个Wicket实例-Hello World! 1.Hello World原版 在Wic ...
- android开发设计辅助工具整理
1.Button设计工具button设计
- php课程 11-37 类和对象的关系是什么
php课程 11-37 类和对象的关系是什么 一.总结 一句话总结:类生成对象,对象是类的实例化,一定是先有类,后有对象,一定是先有标准,再有个体. 1.oop的三大优势是什么? 重用性,灵活性.扩展 ...