簡介
動畫是在開發(fā)中比不缺少的展示形式,可以為整個APP增加很多逼格。android動畫中分為屬性動畫和補(bǔ)間動畫。補(bǔ)間動畫比較簡單但是也有不足的地方就是,動畫的移動只是表面,真實的坐標(biāo)還是原來的位置,如果處理一些事件就比較尷尬了。所以就一起來了解了解屬性動畫。
相關(guān)API
Property Animation故名思議就是通過動畫的方式改變對象的屬性了,我們首先需要了解幾個屬性:
- Duration動畫的持續(xù)時間,默認(rèn)300ms。
- Time interpolation:時間差值,乍一看不知道是什么,但是我說LinearInterpolator、AccelerateDecelerateInterpolator,大家一定知道是干嘛的了,定義動畫的變化率。
- Repeat count and behavior:重復(fù)次數(shù)、以及重復(fù)模式;可以定義重復(fù)多少次;重復(fù)時從頭開始,還是反向。
- Animator sets: 動畫集合,你可以定義一組動畫,一起執(zhí)行或者順序執(zhí)行。
- Frame refresh delay:幀刷新延遲,對于你的動畫,多久刷新一次幀;默認(rèn)為10ms,但最終依賴系統(tǒng)的當(dāng)前狀態(tài);基本不用管。
相關(guān)的類 - ObjectAnimator 動畫的執(zhí)行類。
- ValueAnimator 動畫的執(zhí)行類。
- AnimatorSet 用于控制一組動畫的執(zhí)行:線性,一起,每個動畫的先后執(zhí)行等。
- AnimatorInflater 用戶加載屬性動畫的xml文件。
- TypeEvaluator 類型估值,主要用于設(shè)置動畫操作屬性的值。
- TimeInterpolator 時間插值,上面已經(jīng)介紹。
總的來說,屬性動畫就是,動畫的執(zhí)行類來設(shè)置動畫操作的對象的屬性、持續(xù)時間,開始和結(jié)束的屬性值,時間差值等,然后系統(tǒng)會根據(jù)設(shè)置的參數(shù)動態(tài)的變化對象的屬性。
效果圖
我們先看下要實現(xiàn)的效果圖如下:

41654616.gif
實現(xiàn)
通過效果圖我們可以看到,是一個圓形從左上角移動到右下角,并且顏色是從藍(lán)色漸變到紅色。那么我們可以分為三步走:
- 繪制出一個圓形。
- 實現(xiàn)位移動畫。
- 實現(xiàn)漸變動畫。
- 效果整合。
一、繪制圓形,此處就直接省略不在介紹了,
二、位移動畫,這里我們就要用到剛才介紹到的一個接口TypeEvaluator。通過實現(xiàn)TypeEvaluator接口中的evaluate方法。以下是實現(xiàn)代碼:
public class PointEvaluator implements TypeEvaluator{
@Override
public Object evaluate(float fraction, Object startValue, Object endValue) {
Point startPoint = (Point) startValue;
Point endPoint = (Point) endValue;
float x = startPoint.getX()+fraction*(endPoint.getX()-startPoint.getX());
float y = startPoint.getY()+fraction*(endPoint.getY()-startPoint.getY());
return new Point(x,y);
}
}
三、 漸變動畫,同位移動畫一樣。
public class ColorEvaluator implements TypeEvaluator {
private int currentRed = -1;
private int currentBlue = -1;
private int currentGreen = -1;
@Override
public Object evaluate(float fraction, Object startValue, Object endValue) {
//獲取開始顏色、結(jié)束顏色的值
String startColor = (String) startValue;
String endColor = (String) endValue;
//獲取RGB的值
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 (currentRed == -1) {
currentRed = startRed;
}
if (currentGreen == -1) {
currentGreen = startGreen;
}
if (currentBlue == -1) {
currentBlue = startBlue;
}
//計算顏色差
int diffRed = Math.abs(startRed - endRed);
int diffGreen = Math.abs(startGreen - endGreen);
int diffBlue = Math.abs(startBlue - endBlue);
int diffColor = diffRed + diffGreen + diffBlue;
//計算當(dāng)前顏色值
if (currentRed!=endRed){
currentRed = Math.abs(getCurrentColor(startRed, endRed, diffColor, 0, fraction));
}else if (currentGreen!=endGreen){
currentGreen = Math.abs(getCurrentColor(startGreen,endGreen,diffColor,diffRed,fraction));
}else if (currentBlue!=endBlue){
currentBlue = Math.abs(getCurrentColor(startBlue,endBlue,diffColor,diffRed+diffGreen,fraction));
}
//將當(dāng)前的值合并成string顏色
String currentColor = "#"+getHexString(currentRed)+getHexString(currentGreen)+getHexString(currentBlue);
return currentColor;
}
private int getCurrentColor(int startColor, int endColor, int diffColor, int i, float fraction) {
int currentColor;
if (startColor > endColor) {
currentColor = (int) (startColor - (fraction * endColor - i));
if (currentColor < endColor) {
currentColor = endColor;
}
} else {
currentColor = (int) (startColor - (fraction * endColor - i));
if (currentColor > endColor) {
currentColor = endColor;
}
}
return currentColor;
}
private String getHexString(int color){
String toHexString = Integer.toHexString(color);
if (toHexString.length()==1){
toHexString = "0"+toHexString;
}
return toHexString;
}
}
四、最后放上整個view的代碼,如下:
public class RoundView extends View {
private float radius = 100f;
private Paint paint;
private Point currentPoint;
private String color;
public RoundView(Context context) {
super(context);
init();
}
public RoundView(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
public RoundView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init();
}
private void init() {
paint = new Paint(Paint.ANTI_ALIAS_FLAG);
paint.setColor(Color.RED);
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
if (currentPoint ==null){
currentPoint = new Point(radius,radius);
startAnimation();
}
canvas.drawCircle(currentPoint.getX(), currentPoint.getY(),radius,paint);
}
private void startAnimation() {
Point startPoint = new Point(radius,radius);
Point endPoint = new Point(getWidth()-radius,getHeight()-radius);
ValueAnimator valueAnimator = ValueAnimator.ofObject(new PointEvaluator(), startPoint, endPoint);
valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator valueAnimator) {
currentPoint = (Point) valueAnimator.getAnimatedValue();
invalidate();
}
});
ObjectAnimator objectAnimator = ObjectAnimator.ofObject(this,"color",new ColorEvaluator(),"#0000FF","#FF0000");
objectAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator valueAnimator) {
String currentColor = (String) valueAnimator.getAnimatedValue();
Logger.e(RoundView.class.getSimpleName(),currentColor);
}
});
AnimatorSet animatorSet = new AnimatorSet();
animatorSet.play(valueAnimator).with(objectAnimator);
animatorSet.setDuration(5000);
animatorSet.start();
}
public String getColor() {
return color;
}
public void setColor(String color) {
this.color = color;
paint.setColor(Color.parseColor(color));
invalidate();
}}