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

Android群英转读书笔记第七章(Android动画机制与使用技巧)

2016-06-01 14:36 573 查看

动画的分类

动画分为视图动画(View)和属性动画(Property),而视图动画又分为Tween动画和Frame动画,属性动画又分为ValueAnimator和ObjectAnimator.

属性动画简介

从Android3.0开始出现,真实改变View的属性,可以响应事件

使用ObjectAnimator时,对象的属性必须有get和set方法,因为内部会通过反射来调用属性的set方法,如果一个属性没有get和set方法,可以通过下面两种方式来解决。

1.自定义一个属性类或者包装类

2.使用ValueAnimator

public class WrapperView {
private View mTargetView;

public WrapperView(View targetView){
mTargetView = targetView;
}
public int getWidth(){
return mTargetView.getLayoutParams().width;
}
public void setWidth(int width){
mTargetView.getLayoutParams().width = width;
mTargetView.requestLayout();
}
}


public class MainActivity extends AppCompatActivity {

private WrapperView wrapperView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Button btn = (Button) findViewById(R.id.button);
wrapperView = new WrapperView(btn);
}
public void click(View view){
ObjectAnimator.ofInt(wrapperView,"width",0,500).setDuration(5000).start();
}
}




在属性动画中,使用PropertyValueHolder可以使多个动画共同作用,用法类似于AnimationSet的使用。

ValueAnimator

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



//创建对象
ValueAnimator valueAnimator = ValueAnimator.ofFloat(0,1);
//设置要添加动画的view
valueAnimator.setTarget(btn);
valueAnimator.setDuration(4000);
//启动动画
valueAnimator.start();
//添加监听
valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
//不断获取动画过程中的值
float animatedValue = (float) animation.getAnimatedValue();
btn.setAlpha(animatedValue);
}
});


AnimatorSet也可以对一个属性进行多个动画,还能控制顺序,比前面的PropertyValueHolder更强大。

View的animate方法

在API16之后,提供了animate方法直接驱动属性动画



btn.animate().alpha(0).y(200).setDuration(2000)
.withStartAction(new Runnable() {
@Override
public void run() {
Toast.makeText(MainActivity.this, "开始", Toast.LENGTH_SHORT).show();
}
}).withEndAction(new Runnable() {
@Override
public void run() {
Toast.makeText(MainActivity.this, "结束", Toast.LENGTH_SHORT).show();
}
});
}


布局动画

布局动画是指作用在ViewGroup上,给ViewGroup添加View时增加一个动画效果。



protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ll = (LinearLayout) findViewById(R.id.ll);
TranslateAnimation animation = new TranslateAnimation(720,0,0,0);
animation.setDuration(2000);
LayoutAnimationController controller = new LayoutAnimationController(animation,0.5f);
controller.setOrder(LayoutAnimationController.ORDER_NORMAL);
ll.setLayoutAnimation(controller);
addView();
}
public void addView(){
for (int i = 0; i < 10; i++) {
TextView textView  = new TextView(this);
textView.setText("文字"+i);
LinearLayout.LayoutParams params = new LinearLayout.LayoutParams
(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
ll.addView(textView,params);
}
}


自定义动画

步骤:

1.重写initialize方法做初始化动作

2.重写applyTransformation方法



public class RotateAnim extends Animation {
private int mCenterWidth;
private int mCenterHeight;
private Camera camera = 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) {
super.applyTransformation(interpolatedTime, t);
Matrix matrix = t.getMatrix();
camera.save();
camera.rotateY(mRotateY*interpolatedTime);
camera.getMatrix(matrix);
camera.restore();
//设置旋转中心,
matrix.preTranslate(mCenterWidth/2,mCenterHeight);
matrix.postTranslate(-mCenterWidth/2,-mCenterHeight);
}
}


Android 5.X SVG 矢量动画机制

SVG是可伸缩矢量图形,使用XML格式定义图形,图像在放大或者改变尺寸的情况下图像质量不会有损失。

Android中使用SVG需要使用下面两个API

VectorDrawable:创建基于XML的SVG图形

AnimatedVerctorDrawable:实现动画效果,比喻为一个胶水,连接静态的VectorDrawable和动态的objectAnimator

动画特效



public class MainActivity extends AppCompatActivity {

private LinearLayout hiddenView;
private LinearLayout ll;
private boolean flag = false;
private float density;
private int hiddenViewHeight;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
density = getResources().getDisplayMetrics().density;
hiddenViewHeight = (int) (density*40+0.5f);
ll = (LinearLayout) findViewById(R.id.ll);
hiddenView = (LinearLayout) findViewById(R.id.hiddenView);
ll.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if(hiddenView.getVisibility() == View.GONE){
hiddenView.setVisibility(View.VISIBLE);
ValueAnimator animator = createAnimation(hiddenView, 0, hiddenViewHeight);
animator.start();
}else{
int oriHeight = hiddenView.getHeight();
ValueAnimator animator = createAnimation(hiddenView, oriHeight, 0);
animator.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
hiddenView.setVisibility(View.GONE);
}
});
animator.start();
}
}
});
}

public ValueAnimator createAnimation(final View view, int start, int end){
ValueAnimator animator = ValueAnimator.ofInt(start,end);
animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
LinearLayout.LayoutParams params = (LinearLayout.LayoutParams) view.getLayoutParams();
params.height = (int) animation.getAnimatedValue();
view.setLayoutParams(params);
}
});
flag = true;
return animator;
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: