了解屬性動畫

簡介

動畫是在開發(fā)中比不缺少的展示形式,可以為整個APP增加很多逼格。android動畫中分為屬性動畫和補(bǔ)間動畫。補(bǔ)間動畫比較簡單但是也有不足的地方就是,動畫的移動只是表面,真實的坐標(biāo)還是原來的位置,如果處理一些事件就比較尷尬了。所以就一起來了解了解屬性動畫。

相關(guān)API

Property Animation故名思議就是通過動畫的方式改變對象的屬性了,我們首先需要了解幾個屬性:

  1. Duration動畫的持續(xù)時間,默認(rèn)300ms。
  2. Time interpolation:時間差值,乍一看不知道是什么,但是我說LinearInterpolator、AccelerateDecelerateInterpolator,大家一定知道是干嘛的了,定義動畫的變化率。
  3. Repeat count and behavior:重復(fù)次數(shù)、以及重復(fù)模式;可以定義重復(fù)多少次;重復(fù)時從頭開始,還是反向。
  4. Animator sets: 動畫集合,你可以定義一組動畫,一起執(zhí)行或者順序執(zhí)行。
  5. Frame refresh delay:幀刷新延遲,對于你的動畫,多久刷新一次幀;默認(rèn)為10ms,但最終依賴系統(tǒng)的當(dāng)前狀態(tài);基本不用管。
    相關(guān)的類
  6. ObjectAnimator 動畫的執(zhí)行類。
  7. ValueAnimator 動畫的執(zhí)行類。
  8. AnimatorSet 用于控制一組動畫的執(zhí)行:線性,一起,每個動畫的先后執(zhí)行等。
  9. AnimatorInflater 用戶加載屬性動畫的xml文件。
  10. TypeEvaluator 類型估值,主要用于設(shè)置動畫操作屬性的值。
  11. TimeInterpolator 時間插值,上面已經(jīng)介紹。
    總的來說,屬性動畫就是,動畫的執(zhí)行類來設(shè)置動畫操作的對象的屬性、持續(xù)時間,開始和結(jié)束的屬性值,時間差值等,然后系統(tǒng)會根據(jù)設(shè)置的參數(shù)動態(tài)的變化對象的屬性。

效果圖

我們先看下要實現(xiàn)的效果圖如下:

41654616.gif

實現(xiàn)

通過效果圖我們可以看到,是一個圓形從左上角移動到右下角,并且顏色是從藍(lán)色漸變到紅色。那么我們可以分為三步走:

  1. 繪制出一個圓形。
  2. 實現(xiàn)位移動畫。
  3. 實現(xiàn)漸變動畫。
  4. 效果整合。

一、繪制圓形,此處就直接省略不在介紹了,
二、位移動畫,這里我們就要用到剛才介紹到的一個接口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();
    }}

以上就是簡單的實現(xiàn)效果圖的全部過程,如有疑問或者更好的建議請留言或者直接聯(lián)系我。謝謝支持!

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容