1. View动画
1.1 View动画的种类
-
TranslateAnimation
:<transalate>
平移动画 -
ScaleAnimation
:<ScaleAnimation>
缩放动画 -
RotateAnimation
:<RotateAnimation>
旋转动画 -
AlphaAnimation
:<AlphaAnimation>
透明度动画
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
final Button btn = findViewById(R.id.btn);
btn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Animation animation = AnimationUtils.loadAnimation(getBaseContext(), R.anim.animation_test);
btn.startAnimation(animation);
}
});
}
}
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
<translate
android:fromXDelta="0"
android:fromYDelta="0"
android:toXDelta="100"
android:toYDelta="100"
android:interpolator="@android:anim/linear_interpolator"
android:duration="100"/>
<rotate
android:duration="100"
android:fromDegrees="0"
android:toDegrees="90"/>
</set>
1.2 自定义动画
- 继承
Animation
抽象类,重写initialize
和applyTransformation
方法 - 主要涉及矩阵变化过程
public class Rotate3dAnimation extends Animation {
private final float mFromDegree;
private final float mToDegree;
private final float mCenterX;
private final float mCenterY;
private final float mDepthZ;
private final boolean mReverse;
private Camera mCamera;
public Rotate3dAnimation(float fromDegree, float toDegree, float centerX, float centerY, float DepthZ, boolean reverse) {
mFromDegree = fromDegree;
mToDegree = toDegree;
mCenterX = centerX;
mCenterY = centerY;
mDepthZ = DepthZ;
mReverse = reverse;
}
@Override
public void initialize(int width, int height, int parentWidth, int parentHeight) {
super.initialize(width, height, parentWidth, parentHeight);
mCamera = new Camera();
}
@Override
protected void applyTransformation(float interpolatedTime, Transformation t) {
super.applyTransformation(interpolatedTime, t);
final float fromDegree = mFromDegree;
float degree = fromDegree + (mFromDegree - fromDegree) * interpolatedTime;
final float centerX = mCenterX;
final float centerY = mCenterY;
final Camera camera = mCamera;
final Matrix matrix = t.getMatrix();
camera.save();
if(mReverse) {
camera.translate(0.0f, 0.0f, mDepthZ * interpolatedTime);
} else {
camera.translate(0.0f, 0.0f, mDepthZ * (1.0f - interpolatedTime));
}
camera.rotateY(degree);
camera.getMatrix(matrix);
camera.restore();
matrix.preTranslate(-centerX, -centerY);
matrix.preTranslate(centerX, centerY);
}
}
1.3 帧动画
帧动画是按顺序播放一组预先设定好的图片
<?xml version="1.0" encoding="utf-8"?>
<animation-list xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="@color/colorPrimaryDark" android:duration="500"/>
<item android:drawable="@color/colorPrimary" android:duration="500" />
<item android:drawable="@color/colorAccent" android:duration="500" />
</animation-list>
button.setBackgroundResource(R.drawable.animation_drawable);
AnimationDrawable animationDrawable =(AnimationDrawable)button.getBackground();
animationDrawable.start();
帧动画
2. View动画的特殊使用场景
2.1 LayoutAnimation
- 作用于
ViewGroup
,子元素出场时都会具有这种动画效果 - 一般用于
ListView
这类有子布局的控件
步骤一:定义LayoutAnimation
<?xml version="1.0" encoding="utf-8"?>
<layoutAnimation xmlns:android="http://schemas.android.com/apk/res/android"
android:delay="0.5"
android:animationOrder="normal"
android:animation="@anim/layout_animation"/>
步骤二:为元素设置具体的出场动画
步骤三:为ViewGroup指定layoutAnimation
属性
不仅可以通过XML文件,还可以使用LayoutAnimationController
进行实现动画
2.2 Activity的切换效果
-
Activity
的默认切换效果是可以变的,主要用到overridePendingTransition(int enterAnim, int exitAnim)
-
overridePendingTransition
需要放在startActivity
或者finish
之后才能生效
3. 属性动画
- 可以不借助对象来实现动画
3.1 使用属性动画
- 必须在API 11以上使用,低版本可使用NineOldAndroids兼容
- 属性动画需要定义在res/animator/下
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
ObjectAnimator.ofFloat(button,"translationY", -button.getHeight()).start();
}
});
属性动画
- 属性动画除了用代码定义还可以用XML来定义
<objectAnimator xmlns:android="http://schemas.android.com/apk/res/android"
android:duration="1000"
android:valueTo="200"
android:valueType="floatType|intType"
android:propertyName="y"
android:repeatCount="1"
android:repeatMode="reverse"/>
-
repeatCount
:-1表示无限循环,默认为0 -
repeatMode
:repeat
|reverse
3.2 理解插值器和估值器
- 插值器:根据时间流逝的白分比来计算当前属性值改变的百分比,系统预置的有
LinearInterpolator
,AccelarateDeccelerateInterpolator
,DeccelarateInterpolator
- 估值器:根据属性改变的百分比来计算改变后的属性值,系统预置的有
IntEvaluator
,FloatEvaluator
,ArgbEvaluator
3.3 属性动画的监听器
- 属性动画提供了用于监听动画的播放过程的方法,主要有
AnimatorUpdateListener
和AnimatorListener
valueAnimator = ValueAnimator.ofFloat(0f, 1f);
valueAnimator.setDuration(1000);
valueAnimator.addListener(new Animator.AnimatorListener() {
@Override
public void onAnimationStart(Animator animation) {
}
@Override
public void onAnimationEnd(Animator animation) {
System.out.println("valueAnimator.isRunning() " + valueAnimator.isRunning());
}
@Override
public void onAnimationCancel(Animator animation) {
}
@Override
public void onAnimationRepeat(Animator animation) {
}
});
valueAnimator.start();
- 系统提供了
AnimatorListenerAdapter
,可以有选择地监听动画
ValueAnimator fadeAnim = ObjectAnimator.ofFloat(newBall, "alpha", 1f, 0f);
fadeAnim.setDuration(250);
fadeAnim.addListener(new AnimatorListenerAdapter() {
public void onAnimationEnd(Animator animation) {
balls.remove(((ObjectAnimator)animation).getTarget());
}
- 系统提供了
AnimatorUpdateListener
,每帧都会回调onAnimationUpdate
animation.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator updatedAnimation) {
// You can use the animated value in a property that uses the
// same type as the animation. In this case, you can use the
// float value in the translationX property.
float animatedValue = (float)updatedAnimation.getAnimatedValue();
textView.setTranslationX(animatedValue);
}
});
3.4 对任意属性做动画
如果想让属性动画生效,必须满足两个条件:
1)object
必须提供setAbc
方法,如果动画的时候没有传递初始值,则还要提供getAbc
方法,否则会crash
2)object
的setAbc
对属性abc
的改变必须能够通过某种方法反映出来,比如会改变UI,否则会无效
如果属性动画想改变的属性不存在,想自定义改变的属性时,有3种方法
1. 给你的对象加上get和set方法,如果有权限的话
系统自带的控件都写在Android SDK中,因此只能对自定义View
起作用
2. 用一个类来包装原始对象,间接为其提供get和set方法
步骤一:新建wrapper
类,传入object
对象
步骤二:在wrapper
类中实现getAbc
和setAbc
方法
步骤三:对wrapper
对象使用abc
属性
注意:setAbc
中要调用requestLayout
方法
3. 采用ValuAnimator
,监听动画过程,自己实现属性的改变
- valueAnimator不作用于任何object,可以对一个值做动画,在监听过程中改变UI
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
final Button button = findViewById(R.id.btn);
// final Rotate3dAnimation rotate3dAnimation = new Rotate3dAnimation(0, 90, 0, 0,100, false);
// button.setBackgroundResource(R.drawable.animation_drawable);
// AnimationDrawable animationDrawable = (AnimationDrawable)button.getBackground();
// animationDrawable.start();
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
performAnimate(button, button.getWidth(), 500);
}
});
}
private void performAnimate(final Button button, final int width, final int i) {
ValueAnimator valueAnimator = ValueAnimator.ofInt(1, 500);
valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
private IntEvaluator intEvaluator = new IntEvaluator();
@Override
public void onAnimationUpdate(ValueAnimator valueAnimator) {
int currentValue = (int)valueAnimator.getAnimatedValue();
float fraction = (float)valueAnimator.getAnimatedFraction();
button.getLayoutParams().width = intEvaluator.evaluate(fraction, width, i);
button.requestLayout();
}
});
valueAnimator.setDuration(500).start();
}
}
自定义属性动画
网友评论