Android Tween Animation动画效果详解
android,动画,Animation,补间动画,自定义动画2016-11-08
Android动画分类:
1.补间动画 Tween Animation
2.逐帧动画 Frame Animation
下面我们来讲的就是补间动画:
代码:
/**
* 透明度动画
*
* @param view
*/
private void alphaAnimation(View view) {
//初始化动画,参数 1.动画开始透明度 2.动画结束透明度
AlphaAnimation alphaAnimation = new AlphaAnimation(1, 0);
//动画持续时间 Animation类的方法,AlphaAnimation继承自Animation类
alphaAnimation.setDuration(1000);
//是否停留在最后一帧
alphaAnimation.setFillAfter(true);
//设置重复次数
alphaAnimation.setRepeatCount(3);
//执行前的等待时间
alphaAnimation.setStartOffset(100);
//开启执行动画
view.startAnimation(alphaAnimation);
//如果想在动画开始,结束,重复的时候进行一些操作,可以设置动画事件的监听
alphaAnimation.setAnimationListener(new Animation.AnimationListener() {
@Override
public void onAnimationStart(Animation animation) {
//动画开始的时候调用
Log.d("测试", "onAnimationStart");
}
@Override
public void onAnimationEnd(Animation animation) {
//动画结束的时候调用
Log.d("测试", "onAnimationEnd");
}
@Override
public void onAnimationRepeat(Animation animation) {
//动画重复执行的时候调用
Log.d("测试", "onAnimationRepeat");
}
});
}
使用xml文件来配置动画效果:
在res文件夹下新建anim文件夹,这个就是用来放置xml动画文件的文件夹,下面新建test_alpha.xml文件配置文件内容
<?xml version="1.0" encoding="utf-8"?>
<alpha xmlns:android="http://schemas.android.com/apk/res/android"
android:duration="1000"
android:fromAlpha="1"
android:toAlpha="0">
</alpha>
如何调用:
view.startAnimation(AnimationUtils.loadAnimation(MainActivity.this, R.anim.test_alpha));
效果:
/**
* 旋转动画
*
* @param view
*/
private void rotateAnimation(View view) {
//初始化参数 1.开始角度 2.结束角度 3.旋转中心点x轴坐标 4.旋转中心点y轴坐标
RotateAnimation rotateAnimation = new RotateAnimation(0, 360, view.getWidth() / 2, view.getHeight() / 2);
rotateAnimation.setDuration(1000);
view.startAnimation(rotateAnimation);
}
xml:
<?xml version="1.0" encoding="utf-8"?>
<rotate xmlns:android="http://schemas.android.com/apk/res/android"
android:duration="1000"
android:fromDegrees="0"
android:pivotX="50%"
android:pivotY="50%"
android:toDegrees="360">
<!--pivotX 旋转中心的x坐标 50%即是相对于其自身宽度的50%
pivotY 旋转中心的y坐标
fromDegrees 开始角度
toDegrees 结束角度 -->
</rotate>
效果:
/**
* 位移动画
*
* @param view
*/
private void translateAnimation(View view) {
//参数1.开始x轴位置 2.移动到x轴的位置 3.开始的y轴位置 4.移动到y轴的位置
TranslateAnimation translateAnimation = new TranslateAnimation(view.getWidth(), view.getWidth(), 0, view.getHeight());
translateAnimation.setDuration(1000);
translateAnimation.setFillAfter(true);
view.startAnimation(translateAnimation);
}
xml:
<?xml version="1.0" encoding="utf-8"?>
<translate xmlns:android="http://schemas.android.com/apk/res/android"
android:fromXDelta="0"
android:fromYDelta="0"
android:duration="1000"
android:toXDelta="100%"
android:toYDelta="100%">
</translate>
效果:
/**
* 缩放动画
*
* @param view
*/
private void scaleAnimation(View view) {
//1.从x轴的缩放比例 2.到x轴的缩放比例 3.从y轴的缩放比例 4.到y轴的缩放比例 5.缩放中心点的x坐标 6.缩放中心点的y坐标
ScaleAnimation scaleAnimation = new ScaleAnimation(0, 1, 0, 1, view.getWidth() / 2, view.getHeight() / 2);
scaleAnimation.setDuration(1000);
view.startAnimation(scaleAnimation);
}
xml:
<?xml version="1.0" encoding="utf-8"?>
<scale xmlns:android="http://schemas.android.com/apk/res/android"
android:duration="1000"
android:fromXScale="1"
android:fromYScale="1"
android:pivotX="50%"
android:pivotY="50%"
android:toXScale="2"
android:toYScale="2">
</scale>
效果:
/**
* 混合动画
*
* @param v
*/
private void animationSet(View v) {
//获取屏幕宽度
WindowManager wm = getWindowManager();
int width = wm.getDefaultDisplay().getWidth();
//1.是否共用插值器
AnimationSet animationSet = new AnimationSet(true);
//位移
TranslateAnimation translateAnimation = new TranslateAnimation(0, width / 2 - v.getWidth() / 2, 0, 0);
translateAnimation.setDuration(0);
animationSet.addAnimation(translateAnimation);
//缩放
ScaleAnimation scaleAnimation = new ScaleAnimation(0, 3, 0, 3, width / 2, v.getHeight() / 2);
scaleAnimation.setDuration(3000);
animationSet.addAnimation(scaleAnimation);
//透明度
AlphaAnimation alphaAnimation = new AlphaAnimation(0, 1);
alphaAnimation.setDuration(3000);
animationSet.addAnimation(alphaAnimation);
//旋转
RotateAnimation rotateAnimation = new RotateAnimation(0, 360, width / 2, v.getHeight() / 2);
rotateAnimation.setDuration(3000);
animationSet.addAnimation(rotateAnimation);
v.startAnimation(animationSet);
}
xml:
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
android:duration="1000"
android:shareInterpolator="true">
<alpha
android:fromAlpha="0"
android:toAlpha="1"></alpha>
<translate
android:fromXDelta="0"
android:fromYDelta="0"
android:toXDelta="100%"
android:toYDelta="100%"></translate>
</set>
AnimationSet就是一个动画集合将所有东西糅合子啊一起执行
效果:
在写自定义动画之前,先来看看AlphaAnimation类的源码:
/*
* 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 alpha level of an object.
* Useful for fading things in and out. This animation ends up
* changing the alpha property of a {@link Transformation}
*
*/
public class AlphaAnimation extends Animation {
private float mFromAlpha;
private float mToAlpha;
/**
* Constructor used when an AlphaAnimation is loaded from a resource.
*
* @param context Application context to use
* @param attrs Attribute set from which to read values
*/
public AlphaAnimation(Context context, AttributeSet attrs) {
super(context, attrs);
TypedArray a =
context.obtainStyledAttributes(attrs, com.android.internal.R.styleable.AlphaAnimation);
mFromAlpha = a.getFloat(com.android.internal.R.styleable.AlphaAnimation_fromAlpha, 1.0f);
mToAlpha = a.getFloat(com.android.internal.R.styleable.AlphaAnimation_toAlpha, 1.0f);
a.recycle();
}
/**
* Constructor to use when building an AlphaAnimation from code
*
* @param fromAlpha Starting alpha value for the animation, where 1.0 means
* fully opaque and 0.0 means fully transparent.
* @param toAlpha Ending alpha value for the animation.
*/
public AlphaAnimation(float fromAlpha, float toAlpha) {
mFromAlpha = fromAlpha;
mToAlpha = toAlpha;
}
/**
* Changes the alpha property of the supplied {@link Transformation}
*/
@Override
protected void applyTransformation(float interpolatedTime, Transformation t) {
final float alpha = mFromAlpha;
t.setAlpha(alpha + ((mToAlpha - alpha) * interpolatedTime));
}
@Override
public boolean willChangeTransformationMatrix() {
return false;
}
@Override
public boolean willChangeBounds() {
return false;
}
/**
* @hide
*/
@Override
public boolean hasAlpha() {
return true;
}
}
发现AlphaAnimation继承自Animation类,所重写的方法有:
1.applyTransformation
这个方法会被父类不断的调用,其中有两个参数
a.float interpolatedTime 这个参数会在动画的执行过程中不断的变化,从开始的时候为0,一直到结束的时候为1
b.Transformation t 这个类中封装了一些属性供子类调用
来看下其具体代码:
@Override
protected void applyTransformation(float interpolatedTime, Transformation t) {
final float alpha = mFromAlpha;
t.setAlpha(alpha + ((mToAlpha - alpha) * interpolatedTime));
}
代码很简单通过t.setAlpha()这个方法去改变控件的alpha属性,然后通过一次次的调用来达到动画的效果
2.willChangeTransformationMatrix
这个方法大概的意思就是该动画是否会改变Matrix矩阵,父类Animaction默认返回true,因为AlphaAnimation只是对透明度的改变不会改变Matrix,所以返回false
3.willChangeBounds
这个方法的意思是动画是否影响指定的视图范围,父类Animaction默认返回true,同理AlphaAnimation返回false
4.hasAlpha
是否有透明度的变化,Animaction默认返回false
AlphaAnimation类除了构造方法之外就这有那么多东西
在来看看RotateAnimation类:
/*
* 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 rotation of an object. This rotation takes
* place in the X-Y plane. You can specify the point to use for the center of
* the rotation, where (0,0) is the top left point. If not specified, (0,0) is
* the default rotation point.
*
*/
public class RotateAnimation extends Animation {
private float mFromDegrees;
private float mToDegrees;
private int mPivotXType = ABSOLUTE;
private int mPivotYType = ABSOLUTE;
private float mPivotXValue = 0.0f;
private float mPivotYValue = 0.0f;
private float mPivotX;
private float mPivotY;
/**
* Constructor used when a RotateAnimation is loaded from a resource.
*
* @param context Application context to use
* @param attrs Attribute set from which to read values
*/
public RotateAnimation(Context context, AttributeSet attrs) {
super(context, attrs);
TypedArray a = context.obtainStyledAttributes(attrs,
com.android.internal.R.styleable.RotateAnimation);
mFromDegrees = a.getFloat(
com.android.internal.R.styleable.RotateAnimation_fromDegrees, 0.0f);
mToDegrees = a.getFloat(com.android.internal.R.styleable.RotateAnimation_toDegrees, 0.0f);
Description d = Description.parseValue(a.peekValue(
com.android.internal.R.styleable.RotateAnimation_pivotX));
mPivotXType = d.type;
mPivotXValue = d.value;
d = Description.parseValue(a.peekValue(
com.android.internal.R.styleable.RotateAnimation_pivotY));
mPivotYType = d.type;
mPivotYValue = d.value;
a.recycle();
initializePivotPoint();
}
/**
* Constructor to use when building a RotateAnimation from code.
* Default pivotX/pivotY point is (0,0).
*
* @param fromDegrees Rotation offset to apply at the start of the
* animation.
*
* @param toDegrees Rotation offset to apply at the end of the animation.
*/
public RotateAnimation(float fromDegrees, float toDegrees) {
mFromDegrees = fromDegrees;
mToDegrees = toDegrees;
mPivotX = 0.0f;
mPivotY = 0.0f;
}
/**
* Constructor to use when building a RotateAnimation from code
*
* @param fromDegrees Rotation offset to apply at the start of the
* animation.
*
* @param toDegrees Rotation offset to apply at the end of the animation.
*
* @param pivotX The X coordinate of the point about which the object is
* being rotated, specified as an absolute number where 0 is the left
* edge.
* @param pivotY The Y coordinate of the point about which the object is
* being rotated, specified as an absolute number where 0 is the top
* edge.
*/
public RotateAnimation(float fromDegrees, float toDegrees, float pivotX, float pivotY) {
mFromDegrees = fromDegrees;
mToDegrees = toDegrees;
mPivotXType = ABSOLUTE;
mPivotYType = ABSOLUTE;
mPivotXValue = pivotX;
mPivotYValue = pivotY;
initializePivotPoint();
}
/**
* Constructor to use when building a RotateAnimation from code
*
* @param fromDegrees Rotation offset to apply at the start of the
* animation.
*
* @param toDegrees Rotation offset to apply at the end of the animation.
*
* @param pivotXType Specifies how pivotXValue should be interpreted. One of
* Animation.ABSOLUTE, Animation.RELATIVE_TO_SELF, or
* Animation.RELATIVE_TO_PARENT.
* @param pivotXValue The X coordinate of the point about which the object
* is being rotated, specified as an absolute number where 0 is the
* left edge. This value can either be an absolute number if
* pivotXType is ABSOLUTE, or a percentage (where 1.0 is 100%)
* otherwise.
* @param pivotYType Specifies how pivotYValue should be interpreted. One of
* Animation.ABSOLUTE, Animation.RELATIVE_TO_SELF, or
* Animation.RELATIVE_TO_PARENT.
* @param pivotYValue The Y coordinate of the point about which the object
* is being rotated, specified as an absolute number where 0 is the
* top edge. This value can either be an absolute number if
* pivotYType is ABSOLUTE, or a percentage (where 1.0 is 100%)
* otherwise.
*/
public RotateAnimation(float fromDegrees, float toDegrees, int pivotXType, float pivotXValue,
int pivotYType, float pivotYValue) {
mFromDegrees = fromDegrees;
mToDegrees = toDegrees;
mPivotXValue = pivotXValue;
mPivotXType = pivotXType;
mPivotYValue = pivotYValue;
mPivotYType = pivotYType;
initializePivotPoint();
}
/**
* Called at the end of constructor methods to initialize, if possible, values for
* the pivot point. This is only possible for ABSOLUTE pivot values.
*/
private void initializePivotPoint() {
if (mPivotXType == ABSOLUTE) {
mPivotX = mPivotXValue;
}
if (mPivotYType == ABSOLUTE) {
mPivotY = mPivotYValue;
}
}
@Override
protected void applyTransformation(float interpolatedTime, Transformation t) {
float degrees = mFromDegrees + ((mToDegrees - mFromDegrees) * interpolatedTime);
float scale = getScaleFactor();
if (mPivotX == 0.0f && mPivotY == 0.0f) {
t.getMatrix().setRotate(degrees);
} else {
t.getMatrix().setRotate(degrees, mPivotX * scale, mPivotY * scale);
}
}
@Override
public void initialize(int width, int height, int parentWidth, int parentHeight) {
super.initialize(width, height, parentWidth, parentHeight);
mPivotX = resolveSize(mPivotXType, mPivotXValue, width, parentWidth);
mPivotY = resolveSize(mPivotYType, mPivotYValue, height, parentHeight);
}
}
一看到除了构造方法外重写的父类的方法又多了一个initialize();只看方法名也看的出来这是一个初始化的方法,在动画开始之前会调用这个方法,其中传递过来的参数分别是,动画目标对象的宽高以及其父对象的宽高,然后在applyTransformation中通过t.getMatrix()获取到矩阵,去执行旋转的方法。
至于其他的ScaleAnimation和TranslateAnimation也都是重写了initialize()和applyTransformation()通过Matrix矩阵来不断的修改属性来达到动画的效果
只要明白了这个,那么再来写自定义动画就简单多了
下面我们来写一个拉伸的动画效果:
代码:
package wkk.app12;
import android.view.animation.Animation;
import android.view.animation.Transformation;
/**
* Created by wkk on 2016/11/8.
*/
public class Animation_m extends Animation {
private int height;
//动画执行之前调用此方法,分别是目标对象以及其父容器的宽高
@Override
public void initialize(int width, int height, int parentWidth, int parentHeight) {
super.initialize(width, height, parentWidth, parentHeight);
this.height = height;
}
@Override
protected void applyTransformation(float interpolatedTime, Transformation t) {
//1.补间 从0至1 本方法将会在动画执行期间不断调用
//x轴 y轴 中心点x轴 y轴
t.getMatrix().setSkew((float) Math.sin(interpolatedTime * 6), 0, 0, height);
}
}
效果:
ps:
起个什么什么详解的名字感觉自己也变成了大神一样,哈哈哈…