属性动画的使用
最近项目中有较多的动画效果,想到这一块还未记录过,于是想着总结一下,下次用到的时候,就来自己的博客看一眼.
-
动画的分类
View动画、帧动画、属性动画
- View动画包括:平移、旋转、缩放、透明度,View动画是一种渐近式动画
- 帧动画:图片切换动画
- 属性动画:通过动态改变对象的属性达到动画效果
View动画
继承自Animation,四个动画效果实现类:TranslateAnimation、ScaleAnimation、RotateAnimation、AlphaAnimation
- XML格式
<?xml version="1.0" encoding="utf-8"?> <set xmlns:android="http://schemas.android.com/apk/res/android" android:interpolator="@android:anim/accelerate_interpolator" android:shareInterpolator="true" android:duration="200" android:fillAfter="true" android:zAdjustment="normal" > <alpha android:interpolator="@android:anim/accelerate_interpolator" android:fromAlpha="float" android:toAlpha="float"/> <scale android:fromXScale="float" android:toXScale="float" android:fromYScale="float" android:toYScale="float" android:pivotX="float" android:pivotY="float"/> <translate android:fromXScale="float" android:toXScale="float" android:fromYScale="float" android:toYScale="float"/> <rotate android:fromDegrees="float" android:toDegrees="float" android:pivotX="float" android:pivotY="float"/> </set>
android:interpolator 表示插值器
android:shareInterpolator 是否共用同一个插值器
android:fillAfter="true" 是否停留结束位置
android:zAdjustment="normal" 设置动画的内容运行时在Z轴上的位置 - 代码使用
Animation animation = AnimationUtils.loadAnimation(this, R.anim.animation); view.startAnimation(animation);
也可以直接代码使用
-
自定义View动画继承Animation,实现initialize、applyTransformation方法,分别处理初始化和矩阵变换采用Camera简化矩阵变换的过程
final Camera camera = new Camera();// 自己创建的Camera final Matrix matrix = t.getMatrix();// 方法传过来的矩阵 camera.save(); camera.translate(0f, 0f, interpolatedTime); camera.getMatrix(matrix); camera.restore();
帧动画
- XML定义
<?xml version="1.0" encoding="utf-8"?> <animation-list xmlns:android="http://schemas.android.com/apk/res/android" android:oneshot="false"> <item android:drawable="@mipmap/ic_launcher" android:duration="100"/> <item android:drawable="@mipmap/ic_launcher" android:duration="100"/> </animation-list>
android:oneshot="false" false 无限循环
- 代码中使用
view.setBackgroundResource(R.drawable.animation_list); AnimationDrawable drawable = (AnimationDrawable)view.getBackground(); drawable.start();
属性动画
- 使用方式一
ObjectAnimator.ofFloat(view, "translationY", 10).start();
- 使用方式二
ValueAnimator valueAnimator = ValueAnimator.ofFloat(0, 1); valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { @Override public void onAnimationUpdate(ValueAnimator valueAnimator) { mAnimatorValue = (float) valueAnimator.getAnimatedValue(); invalidate(); } });
可以在View中使用
插值器:根据时间流逝百分比计算属性值改变百分比
估值器:根据属性值百分比计算改变后的属性值
-
实例
基本用法介绍完了,就来个项目中的实例吧:
这里进入的动画和出来的相反,就不一一例举了.xml中:
java代码:
lyricBtn.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() { @Override public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { Animator scale_in = AnimatorInflater.loadAnimator( rl_lrc.getContext(), R.anim.scale_in); Animator scale_out = AnimatorInflater.loadAnimator( rl_lrc.getContext(), R.anim.scale_out); Animator translate_left_in = AnimatorInflater.loadAnimator( rl_lrc.getContext(), R.anim.translate_left_in); Animator translate_left_out = AnimatorInflater.loadAnimator( rl_lrc.getContext(), R.anim.translate_left_out); Animator translate_right_in = AnimatorInflater.loadAnimator( rl_lrc.getContext(), R.anim.translate_right_in); Animator translate_right_out = AnimatorInflater.loadAnimator( rl_lrc.getContext(), R.anim.translate_right_out); if (isChecked) { //显示歌词 rl_lrc.setVisibility(View.VISIBLE); vp_cover.setVisibility(View.INVISIBLE); rl_animator.setVisibility(View.VISIBLE); scale_in.setTarget(main_bg); scale_in.addListener(new Animator.AnimatorListener() { @Override public void onAnimationStart(Animator animator) { } @TargetApi(Build.VERSION_CODES.LOLLIPOP) @Override public void onAnimationEnd(Animator animator) { main_bg.setElevation(0); } @Override public void onAnimationCancel(Animator animator) { } @Override public void onAnimationRepeat(Animator animator) { } }); scale_in.start(); translate_left_in.setTarget(iv_left); translate_left_in.start(); translate_right_in.setTarget(iv_right); translate_right_in.start(); } else { rl_animator.setVisibility(View.VISIBLE); // vp_cover_lrc.setVisibility(View.INVISIBLE); ValueAnimator animator = ValueAnimator.ofFloat(0f, 200.0f); animator.setTarget(iv_value); animator.setDuration(300); animator.start(); animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { @TargetApi(Build.VERSION_CODES.LOLLIPOP) @Override public void onAnimationUpdate(ValueAnimator valueAnimator) { // 获取当前值 Float mValue = (Float) valueAnimator.getAnimatedValue(); main_bg.setElevation(50 * mValue); } }); //隐藏歌词 rl_lrc.setVisibility(View.INVISIBLE); scale_out.setTarget(main_bg); scale_out.addListener(new Animator.AnimatorListener() { @Override public void onAnimationStart(Animator animator) { } @TargetApi(Build.VERSION_CODES.LOLLIPOP) @Override public void onAnimationEnd(Animator animator) { vp_cover.setVisibility(View.VISIBLE); rl_animator.setVisibility(View.INVISIBLE); } @Override public void onAnimationCancel(Animator animator) { } @Override public void onAnimationRepeat(Animator animator) { } }); scale_out.start(); translate_left_out.setTarget(iv_left); translate_left_out.start(); translate_right_out.setTarget(iv_right); translate_right_out.start(); } } });
歌词模式的切换动画就搞定了,具体地看下效果吧: