您的位置:首页 > 移动开发 > Android开发

《Android群英传》---读书笔记5

2016-12-11 21:40 369 查看
标签: android中级 读书笔记

Android动画机制与使用技巧

包括:

Android视图动画

Android属性动画

还包括下一篇的 Android5.X引入的 SVG 矢量动画

7.1 Android View动画框架

Animation框架定义了透明度,旋转,缩放和位移几种常见的动画,而且控制的是整个View

视图动画使用很简单,提供了AlphaAnimation,RotateAnimation,TranslateAnimation,ScaleAnimation四种动画方式,并且提供了AnimationSet动画集合,混合使用多种动画

可以使用XML文件来描述一个动画过程,同样也可以使用代码来控制整个动画过程

透明度动画

AlphaAnimation aa=new AlphaAnimation(0,1);

aa.setDuration(1000);

view.starAnimation(aa);

旋转动画

RotateAnimation ra=new RotateAnimation(0,360,100,100);

ra.setDuration(1000);

view.startAnimation(ra);

也可以将旋转中心设置为自身中心点

RotateAnimation ra=new RotateAnimation(0,360,RorateAnimation,RELATIVE_TO_SELF,0.5F,RELATIVE_TO_SELF,0.5F);

位移动画

TranslateAnimation ta=new TranslateAnimation(0,200,0,300);

ta.setDuration(1000);

view.startAnimation(ta);

缩放动画

ScaleAnimation sa=new ScaleAnimation(0,2,0,2);

sa.setDuration(1000);

view.startAnimation(sa);

也可以设置旋转中心为自身中心

动画集合

AnimationSet as=new AnimationSet(true);

as.setDuration(1000);

AlphaAnimation aa=new AlphaAnimation(0,1);

aa.setDuration(1000);

as.addAnimation(aa);

TranslateAnimation ta=new TranslateAnimation(0,100,0,200);

ta.setDuration(1000);

as.addAnimation(ta);

view.startAnimation(as);

对于动画事件,可以设置对应的监听回调

animation.setAnimationListener(new Animation.AnimationListener(){

@Override

public void onAnimationStart(Animation animation){

}

@Override

public void onAnimationEnd(Animation animation){

}

@Override

public void onAnimationRepeat(Animation animation){

}

});

7.2 Android属性动画分析

Animation(即视图动画)存在的一些局限性—例如改变的只是显示,不能相应事件,所以引入了属性动画

Animator框架中使用最多就是AnimatorSet和ObjectAnimator配合,使用ObjectAnimator进行更加精细化的控制。而且可以调用setFrameDelay(longframDelay)设置动画帧之间的间隙时间,减少CPU资源的消耗。

7.2.1 ObjectAnimator

使用ObjectAnimator控制的对象的相应属性,该属性必须具有get和set函数。

ObjectAnimator animator =ObjectAnimator.ofFloat(view,”translationX”,300);

animator.setDuration(300);

animator.start();

常用的属性动画的属性值:

translateX和translationY:控制着View对象从它布局容器的左上角坐标的偏移量

rotation,rotationX和rotationY:控制View对象围绕支点进行2D和3D旋转

scaleX和scaleY:围绕支点进行2D缩放

pivotX和pivotY:控制View对象的支点位置,围绕这个支点进行旋转和缩放变换处理。默认情况下就是View对象的中心点

x和y:描述了View对象在它的容器中的最终位置,它是translationX,translationY值得累计和

alpha:表示View对象的alpha透明度

如果一个属性没有get,set方法,可以采用包装类的方式,或者使用ValueAnimator来实现

private static WrapperView{
private View mTarget;
public WrapperView(View target){
mTarget=target;
}
public int getWidth(){
return mTarget.getLayoutParams().width;
}
public void setWidth(){
mTarget.getLayoutParams().width=width;
mTarget.requestLayout();
}
}
然后 就可以通过包装类来间接使用ObjectAnimator来使用属性动画
ViewWrapper wrapper=new ViewWrapper(mButton);
ObjectAnimator.ofInt(wrapper,"width",500).setDuration(5000).start();


7.2.2 PropertyValuesHolder

类似于视图动画中的AnimationSet,在属性动画中,可以使用PropertyValuesHolder来实现对同一个对象的多个属性,同时作用多种动画。例如在平移动画中,在平移的过程中同时改变X,Y轴的缩放

PropertyValuesHolder phv1=PropertyValuesHolder.ofFloat("translationX",300f);
PropertyValuesHolder phv2=PropertyValuesHolder.ofFloat("scaleX",1f,0,1f);
PropertyValuseHolder.ofFloat("scaleY",1f,0,1f);
ObjectAnimator.ofPropertyValuesHolder(view,phv1,phv2,phv3).setDuration(1000).start();


7.2.3 ValueAnimator

ValueAnimator本身不提供任何动画效果,它更像一个数值发生器,用来产生具有一定规律的数值从而让调用者来控制动画的实现过程

ValueAnimator animator=ValueAnimator.ofFloat(0,100);
animator.setTarget(view);
animator.setDuration(3000).start();
animator.addUpdateListener(new AnimatorUpdateListener(){
@Override
public void onAnimatorUpdate(ValueAnimator animation){
Float value=(Float)animation.getAnimatedValue();
//TODO use the value
}
});


7.2.4 动画事件的监听

一个完整的动画具有 Start, Repeat,End,Cancel四个过程,

ObjectAnimator anim=ObjectAnimator.ofFloat(view,"alpha",0.5f);
anim.addListener(new AnimatorListener(){
//some Methods to Override...
});


不过大多数时候我们只关心onAnimationEnd事件,所以只需要通过AnimatorListenerAdapter进行监听就行

anim.addListener(new AnimatorListenerAdapter(){
@Override
public void onAnimationEnd(Animator animation){

}
});


7.2.5 AnimatorSet

AnimatorSet相比PropertyValuesHolder能实现更加精确的控制

ObejectAnimator animator1=ObjectAnimator.ofFloat(view,"translationX",300f);
ObejectAnimator animator2=ObjectAnimator.ofFloat(view,"scaleX",1f,0f,1f);
ObejectAnimator animator3=ObjectAnimator.ofFloat(view,"scaleY",1f,0f,1f);
AnimatorSet set=new AnimatorSet();
set.setDuration(1000);
set.playTogether(animator1,animator2,animator3);
set.start();


AnimatorSet可以通过playTogether(), playSequentially(), animSet.play().with(), before(), after()这些方法来控制多个动画的协同工作方式

7.2.6 在XML中使用属性动画

<?xml version="1.0",encoding="utf-8"?>
<objectAnimator xmlns:android="http://schemas.android.com/apk/res/android"
android:duration="1000"
android:propertyName="scaleX"
android:valueFrom="1.0"
android:valueTo="2.0"
android:valueType="floatType">
</objectAnimator>

然后直接在程序中使用
public void scaleX(View view){
Animator anim=Animator.loadAnimator(this,R.animator.scalex);
anim.setTarget(mMv);
anim.start();
}


7.2.7 View的animate方法

Android 3.0之后,可以使用View的animate方法直接驱动属性动画

view.animate().alpha(0).y(300).setDuration(300).withStartAction(new Runable(){
@Override
public void run(){  }
}).withEndAction(new Runable(){
@Override
public void run(){
runOnUiThread(new Runable(){
@Override
public void run(){  }
}
});
}
}).start();


7.3 Android布局动画

布局动画就是指ViewGroup增加View时添加一个动画过度效果。

最简单的布局动画就是在ViewGroup的XML中,使用以下代码来打开布局动画,从而实现默认的动画效果

android:animateLayoutChanges=”true”

另外还可以使用LayoutAnimationController类来自定义一个子View的过度效果

LinerLayout ll=(LinearLayout)findViewById(R.id.ll);
//设置过度动画
ScaleAnimation sa=new ScaleAnimation(0,1,0,1);
sa.setDuration(2000);
//设置布局动画的显示属性
LayoutAnimatorController lac=new LayoutAnimationController(sa,0.5f);
lac.setOrder(LayoutAnimationController.ORDER_NORMAL);
//为ViewGroup设置布局动画
ll.setLayoutAnimation(lac);

LayoutAnimationController的第一个参数是需要作用的动画,第二个参数是每个子View显示的delay时间。当delay不为0时,可以设置子View的显示顺序


Interpolators(插值器)

通过插值器可以定义动画的变换速率,非常类似于物理中的加速度,其主要作用是控制目标变量的变化值进行对应的变化。在不同的插值器的作用下同一个动画的起始值,每个单位时间内所达到的变化值是不一样的。

7.5 自定义动画、

创建自定义动画非常简单,只需要实现它的applyTransformation的逻辑就可以了,不过通常情况下,还需要覆盖父类的initialize方法来进行一些初始化工作。

applyTransformation(float interpolateTime,Transformation t)//第一个参数为时间因子,取值范围0到1.0;第二个参数为一个矩阵的封装类,一般通过这个类来获得当前的矩阵对象:final Matrix matrix=t.getMatrix();
通过改变获得的matrix对象,就可以将动画效果实现出来


下面的代码示例实现一个类似于电视机关闭的动画

import android.graphics.Camera;
import android.graphics.Matrix;
import android.view.animation.AccelerateInterpolator;
import android.view.animation.Animation;
import android.view.animation.Transformation;

public class CustomTV extends Animation {

private int mCenterWidth;
private int mCenterHeight;
private Camera mCamera = new Camera();
private float mRotateY = 0.0f;

@Override
public void initialize(int width,
int height,
int parentWidth,
int parentHeight) {

super.initialize(width, height, parentWidth, parentHeight);
// 设置默认时长
setDuration(1000);
// 动画结束后保留状态
setFillAfter(true);
// 设置默认插值器
setInterpolator(new AccelerateInterpolator());
mCenterWidth = width / 2;
mCenterHeight = height / 2;
}

// 暴露接口-设置旋转角度
public void setRotateY(float rorateY) {
mRotateY = rorateY;
}

@Override
protected void applyTransformation(
float interpolatedTime,
Transformation t) {
final Matrix matrix = t.getMatrix();
matrix.preScale(1,
1 - interpolatedTime,
mCenterWidth,
mCenterHeight);
}
}


也可以结合矩阵,并使用Camera类来实现一个自定义的3D动画。

这里的Camera类指的是android.graphics.Camera中的Camera类,它封装课openGL的3D动画,从而可以非常方便的创建3D动画效果

import android.graphics.Camera;
import android.graphics.Matrix;
import android.view.animation.Animation;
import android.view.animation.BounceInterpolator;
import android.view.animation.Transformation;

public class CustomAnim extends Animation {

private int mCenterWidth;
private int mCenterHeight;
private Camera mCamera = new Camera();
private float mRotateY = 0.0f;

@Override
public void initialize(int width,
int height,
int parentWidth,
int parentHeight) {

super.initialize(width, height, parentWidth, parentHeight);
// 设置默认时长
setDuration(2000);
// 动画结束后保留状态
setFillAfter(true);
// 设置默认插值器
setInterpolator(new BounceInterpolator());
mCenterWidth = width / 2;
mCenterHeight = height / 2;
}

// 暴露接口-设置旋转角度
public void setRotateY(float rotateY) {
mRotateY = rotateY;
}

@Override
protected void applyTransformation(
float interpolatedTime,
Transformation t) {
final Matrix matrix = t.getMatrix();
mCamera.save();
// 使用Camera设置旋转的角度
mCamera.rotateY(mRotateY * interpolatedTime);
// 将旋转变换作用到matrix上
mCamera.getMatrix(matrix);
mCamera.restore();
// 通过pre方法设置矩阵作用前的偏移量来改变旋转中心
matrix.preTranslate(mCenterWidth, mCenterHeight);
matrix.postTranslate(-mCenterWidth, -mCenterHeight);
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息