Android 屬性動畫
阿新 • • 發佈:2021-02-10
技術標籤:# Android自定義View體系Animator
文章目錄
屬性動畫
概述
- Android3.0之前的動畫框架存在一些缺陷,動畫改變的只是顯示,並不能響應事件。
- 在Android3.0之後,谷歌推出全新的動畫框架,實現機制是通過對目標物件進行賦值並修改其屬性來實現的 。
ObjectAnimator
ObjectAnimator可以直接對任意物件的任意屬性進行動畫操作。
旋轉動畫
ObjectAnimator animator = ObjectAnimator.ofFloat(imageView, ROTATION, 0f, 360f);
animator.setDuration(2000L);
animator.setRepeatCount(3);
animator.start();
平移動畫
float distance = imageView.getTranslationX();
ObjectAnimator animator = ObjectAnimator.ofFloat(imageView, TRANSLATION_X, distance, 500, distance) ;
animator.setDuration(2000L);
animator.setRepeatCount(3);
animator.start();
縮放動畫
ObjectAnimator animator = ObjectAnimator.ofFloat(imageView, SCALE_Y, 1f, 3f, 1f);
animator.setDuration(2000L);
animator.start();
透明度動畫
ObjectAnimator animator = ObjectAnimator.ofFloat(imageView, ALPHA, 1f, 0f, 1f);
animator. setDuration(2000L);
animator.start();
組合動畫
- after(Animator anim) 將現有動畫插入到傳入的動畫之後執行
- after(long delay) 將現有動畫延遲指定毫秒後執行
- before(Animator anim) 將現有動畫插入到傳入的動畫之前執行
- with(Animator anim) 將現有動畫和傳入的動畫同時執行
float distance = imageView.getTranslationX();
ObjectAnimator translation = ObjectAnimator.ofFloat(imageView, TRANSLATION_X, distance, 500, distance);
ObjectAnimator scale = ObjectAnimator.ofFloat(imageView, SCALE_Y, 1f, 3f, 1f);
ObjectAnimator rotation = ObjectAnimator.ofFloat(imageView, ROTATION, 0f, 360f);
ObjectAnimator alpha = ObjectAnimator.ofFloat(imageView, ALPHA, 1f, 0f, 1f);
AnimatorSet animatorSet = new AnimatorSet();
//1.同時執行動畫一
// animatorSet.play(translation).with(scale).with(rotation).with(alpha);
//2.同時執行動畫二
// animatorSet.playTogether(translation, scale, rotation, alpha);
//3.順序執行動畫
// animatorSet.playSequentially(translation, scale, rotation, alpha);
//4.指定順序執行動畫:rotation->translation->scale
animatorSet.play(translation).before(scale).after(rotation);
animatorSet.setDuration(2000);
animatorSet.start();
ValueAnimator
- ObjectAnimator類是屬性動畫中最核心的類,ObjectAnimator繼承於ValueAnimator
- 屬性動畫是通過不斷修改值實現動畫效果,而初始值和結束值之間的變化由該類負責計算
//向右移動500
private void startValueAnimator() {
int distance = 500;
ValueAnimator animator = ValueAnimator.ofFloat(0f, 1f);
animator.setDuration(2000L);
animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
float value = (float) animation.getAnimatedValue();
moveView(imageView, value, distance);
}
});
animator.setInterpolator(new DecelerateInterpolator());
animator.start();
}
private void moveView(View targetView, float value, int distance) {
int left = rawLeft + (int) (value * distance);
int top = targetView.getTop();
int right = left + targetView.getWidth();
int bottom = top + targetView.getHeight();
targetView.layout(left, top, right, bottom);
}
TypeEvaluator 估值器
作用:設定屬性值從初始值過渡到結束值的變化具體數值
動畫的值 = 初始值 + 完成度 * (結束值 - 初始值)
實現了TypeEvaluator
介面,然後重寫了evaluate()
方法,引數有三個,依次是:
- fraction:動畫的完成度,我們根據他來計算動畫的值應該是多少
- startValue:動畫的起始值
- endValue:動畫的結束值
private void startTypeEvaluator() {
ValueAnimator valueAnimator = ValueAnimator.ofObject(new FloatEvaluator(), 0f, 1f);
valueAnimator.setDuration(2000);
valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
float value = (float) animation.getAnimatedValue();
Log.e("TAG", "value:" + value);
}
});
valueAnimator.start();
}
public class FloatEvaluator implements TypeEvaluator {
public Object evaluate(float fraction, Object startValue, Object endValue) {
float startFloat = ((Number) startValue).floatValue();
return startFloat + fraction * (((Number) endValue).floatValue() - startFloat);
}
}
列印資訊
value:0.0
value:0.0
value:0.033116043
value:0.26119065
...
value:0.89794815
value:0.97329646
value:1.0
ViewPropertyAnimator
屬性動畫的機制已經不是再針對於View而進行設計的了,而是一種不斷地對值進行操作的機制,它可以將值賦值到指定物件的指定屬性上。但是,在絕大多數情況下,我相信大家主要都還是對View進行動畫操作的。Android開發團隊也是意識到了這一點,沒有為View的動畫操作提供一種更加便捷的用法確實是有點太不人性化了,於是在Android 3.1系統當中補充了ViewPropertyAnimator這個機制。
//透明度動畫
imageView.animate().alpha(0.5f).setDuration(2000L);
ViewCompat.animate(imageView).alpha(0.5f);
//平移動畫
imageView.animate().translationX(500f).setDuration(2000L);
//旋轉動畫
imageView.animate().rotation(360).setDuration(2000L);
//縮放動畫
imageView.animate().scaleX(1.5F).setDuration(2000L);
ObjectAnimator 高階用法
public class MyAnimView extends View {
public static final int RADIUS = 50;
private Point currentPoint;
private Paint mPaint;
public MyAnimView(Context context, AttributeSet attrs) {
super(context, attrs);
mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
mPaint.setColor(Color.BLUE);
}
@Override
protected void onDraw(Canvas canvas) {
if (currentPoint == null) {
currentPoint = new Point(RADIUS, RADIUS);
drawCircle(canvas);
startAnimation();
} else {
drawCircle(canvas);
}
}
private void drawCircle(Canvas canvas) {
float x = currentPoint.x;
float y = currentPoint.y;
canvas.drawCircle(x, y, RADIUS, mPaint);
}
private void setColor(String color) {
mPaint.setColor(Color.parseColor(color));
}
private void startAnimation() {
Point startPoint = new Point(RADIUS, RADIUS);
Point endPoint = new Point(getWidth(), getHeight());
ValueAnimator anim = ValueAnimator.ofObject(new PointEvaluator(), startPoint, endPoint);
anim.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
currentPoint = (Point) animation.getAnimatedValue();
invalidate();
}
});
ObjectAnimator anim2 = ObjectAnimator.ofObject(this, "color", new ColorEvaluator(), "#0000FF", "#FF0000");
anim2.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
setColor((String) animation.getAnimatedValue());
invalidate();
}
});
AnimatorSet animSet = new AnimatorSet();
animSet.play(anim).with(anim2);
animSet.setDuration(5000);
//速度加快
//animSet.setInterpolator(new AccelerateInterpolator(2f));
//彈跳效果
animSet.setInterpolator(new BounceInterpolator());
animSet.start();
}
public class PointEvaluator implements TypeEvaluator {
@Override
public Object evaluate(float fraction, Object startValue, Object endValue) {
//fraction:動畫的完成度
Point startPoint = (Point) startValue;
Point endPoint = (Point) endValue;
int x = (int) (startPoint.x + fraction * endPoint.x - startPoint.x);
int y = (int) (startPoint.y + fraction * endPoint.y - startPoint.y);
Point point = new Point(x, y);
return point;
}
}
public class ColorEvaluator implements TypeEvaluator {
private int mRed = -1;
private int mGreen = -1;
private int mBlue = -1;
@Override
public Object evaluate(float fraction, Object startValue, Object endValue) {
String startColor = (String) startValue;
String endColor = (String) endValue;
int startRed = Integer.parseInt(startColor.substring(1, 3), 16);
int startGreen = Integer.parseInt(startColor.substring(3, 5), 16);
int startBlue = Integer.parseInt(startColor.substring(5, 7), 16);
int endRed = Integer.parseInt(endColor.substring(1, 3), 16);
int endGreen = Integer.parseInt(endColor.substring(3, 5), 16);
int endBlue = Integer.parseInt(endColor.substring(5, 7), 16);
// 初始化顏色的值
if (mRed == -1) {
mRed = startRed;
}
if (mGreen == -1) {
mGreen = startGreen;
}
if (mBlue == -1) {
mBlue = startBlue;
}
// 計算初始顏色和結束顏色之間的差值
int redDiff = Math.abs(startRed - endRed);
int greenDiff = Math.abs(startGreen - endGreen);
int blueDiff = Math.abs(startBlue - endBlue);
int colorDiff = redDiff + greenDiff + blueDiff;
if (mRed != endRed) {
mRed = getCurrentColor(startRed, endRed, colorDiff, 0, fraction);
} else if (mGreen != endGreen) {
mGreen = getCurrentColor(startGreen, endGreen, colorDiff, redDiff, fraction);
} else if (mBlue != endBlue) {
mBlue = getCurrentColor(startBlue, endBlue, colorDiff, redDiff + greenDiff, fraction);
}
// 將計算出的當前顏色的值組裝返回
String currentColor = "#" + getHexString(mRed) + getHexString(mGreen) + getHexString(mBlue);
return currentColor;
}
/**
* 根據fraction值來計算當前的顏色。
*/
private int getCurrentColor(int startColor, int endColor, int colorDiff,
int offset, float fraction) {
int currentColor;
if (startColor > endColor) {
currentColor = (int) (startColor - (fraction * colorDiff - offset));
if (currentColor < endColor) {
currentColor = endColor;
}
} else {
currentColor = (int) (startColor + (fraction * colorDiff - offset));
if (currentColor > endColor) {
currentColor = endColor;
}
}
return currentColor;
}
/**
* 將10進位制顏色值轉換成16進位制。
*/
private String getHexString(int value) {
String hexString = Integer.toHexString(value);
if (hexString.length() == 1) {
hexString = "0" + hexString;
}
return hexString;
}
}
}