在上一篇中我们使用到了位移动画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】——自定义动画研究的更多相关文章

  1. Android中的动画详解系列【4】——Activity之间切换动画

    前面介绍了Android中的逐帧动画和补间动画,并实现了简单的自定义动画,这一篇我们来看看如何将Android中的动画运用到实际开发中的一个场景--Activity之间跳转动画. 一.定义动画资源 如 ...

  2. Android中Service(服务)详解

    http://blog.csdn.net/ryantang03/article/details/7770939 Android中Service(服务)详解 标签: serviceandroidappl ...

  3. Android中mesure过程详解

    我们在编写layout的xml文件时会碰到layout_width和layout_height两个属性,对于这两个属性我们有三种选择:赋值成具体的数值,match_parent或者wrap_conte ...

  4. Android中Intent组件详解

    Intent是不同组件之间相互通讯的纽带,封装了不同组件之间通讯的条件.Intent本身是定义为一个类别(Class),一个Intent对象表达一个目的(Goal)或期望(Expectation),叙 ...

  5. Android中的动画详解系列【2】——飞舞的蝴蝶

    这一篇来使用逐帧动画和补间动画来实现一个小例子,首先我们来看看Android中的补间动画. Android中使用Animation代表抽象的动画类,该类包括下面几个子类: AlphaAnimation ...

  6. RxJava在Android中使用场景详解

    RxJava 系列文章 <一,RxJava create操作符的用法和源码分析> <二,RxJava map操作符用法详解> <三,RxJava flatMap操作符用法 ...

  7. Android中shape属性详解

    一.简单使用 刚开始,就先不讲一堆标签的意义及用法,先简单看看shape标签怎么用. 1.新建shape文件 首先在res/drawable文件夹下,新建一个文件,命名为:shape_radius.x ...

  8. Android中的Service详解

    今天我们就来介绍一下Android中的四大组件中的服务Service,说到Service, 它分为本地服务和远程服务:区分这两种服务就是看客户端和服务端是否在同一个进程中,本地服务是在同一进程中的,远 ...

  9. Android中Service 使用详解(LocalService + RemoteService)

    Service 简介: Service分为本地服务(LocalService)和远程服务(RemoteService): 1.本地服务依附在主进程上而不是独立的进程,这样在一定程度上节约了资源,另外L ...

随机推荐

  1. jmeter实现分布式压测步骤

    环境说明:安装与控制机相同版本的jdk与jmeter 1.修改控制机中的jmeter.properties文件 将<remote_hosts=127.0.0.1>改为<remote_ ...

  2. Project Euler 435 Polynomials of Fibonacci numbers (矩阵快速幂)

    题目链接: https://projecteuler.net/problem=435 题意: The Fibonacci numbers $ {f_n, n ≥ 0}$ are defined rec ...

  3. 105.UDP通信实现广播

    客户端 #include <stdio.h> #include <string.h> #include <winsock.h> #pragma comment(li ...

  4. Python的主成分分析PCA算法

    这篇文章很不错:https://blog.csdn.net/u013082989/article/details/53792010 为什么数据处理之前要进行归一化???(这个一直不明白) 这个也很不错 ...

  5. Servlet的异常处理机制

    一 声明式异常处理   在web.xml中对声明对各种异常的处理方法. 通过 <error-page>元素来声明. 此元素的结构如下:                    +------ ...

  6. 使用VHD,让Win XP和 Win2003 运行在内存中

    通过一定的手段可以让XP和2003甚至Win7运行在内存中.我很感兴趣,于是按照网上的资料在VBox虚拟机中测试了一次,运行成功.这几天将其折腾到实体机上. 声明:我的做法和网上的做法有些不一样,我的 ...

  7. POJ 2284 That Nice Euler Circuit (LA 3263 HDU 1665)

    http://poj.org/problem?id=2284 https://icpcarchive.ecs.baylor.edu/index.php?option=com_onlinejudge&a ...

  8. web服务器软件(Nginx,Apache,IIS,Lighttpd)介绍

    Nginx是一款轻量级的Web 服务器/反向代理服务器及电子邮件(IMAP/POP3)代理服务器,并在一个BSD-like 协议下发行.其特点是占有内存少,并发能力强,事实上nginx的并发能力确实在 ...

  9. 【Codeforces Round #301 (Div. 2) D】 Bad Luck Island

    [链接] 我是链接,点我呀:) [题意] 剪刀.石头.布各有r,s,p个生活在同一个村子里. 它们两两之间相遇的几率都相同(相遇后就会按照划拳的规则判断输赢,输的人就死掉了). 问你最后只剩下剪刀,只 ...

  10. 【AtCoder Beginner Contest 074 B】Collecting Balls (Easy Version)

    [链接]h在这里写链接 [题意] 看懂题目之后就会发现是道大水题. [题解] 在这里写题解 [错的次数] 0 [反思] 在这了写反思 [代码] #include <bits/stdc++.h&g ...