TypeEvaluator 估值器 拋物線


TypeEvaluator簡介

Android提供了以下幾個簡單的Evalutor實現類:
  • IntEvaluator:屬性的值類型為int
  • FloatEvaluator:屬性的值類型為float
  • ArgbEvaluator:屬性的值類型為十六進制顏色值
TypeEvaluator:一個接口,可以通過實現該接口自定義Evaluator。

TypeEvaluator的實現過程:
首先根據動畫【已進行的時間】跟動畫【總時間】的比計算出一個時間因子(0~1,即evalute()中的fraction參數,這個值是自動計算得到的)
然后根據【TimeInterpolator】得到出另一個算法因子
TypeEvaluator通過這【兩個】因子計算出屬性值並將其【傳給】我們定義的泛型對象
最后在我們監聽動畫的繪制過程中,將泛型對象中保存的值【取出】並用於【更改】目標對象的屬性

自定義TypeEvaluator時傳入的泛型可以根據自己的需求,自己設計個Bean。
只要 evaluate中的函數能夠滿足:當fraction=0時返回值為startValue,並且當fraction=1時返回值為endValue,就是一個比較合理的函數。

TypeEvaluator 接口源碼

/**
* Interface for use with the ValueAnimator#setEvaluator(TypeEvaluator) function. Evaluators
* allow developers to create animations on arbitrary任意的 property types, by allowing them to supply
* custom evaluators for types that are not automatically understood and used by the animation system.
*/
public interface TypeEvaluator<T> {
/**
* This function returns the result of linearly interpolating the start and end values, with fraction representing
* the proportion比例 between the start and end values. The calculation is a simple parametric參數
* calculation: result = x0 + t * (x1 - x0), where "x0" is startValue, "x1" is endValue, and "t" is fraction.
* @param fraction The fraction from the starting to the ending values
* @return A linear interpolation between the start and end values, given the fraction parameter.
*/
public T evaluate(float fraction, T startValue, T endValue);
}

IntEvaluator 源碼

/** This evaluator can be used to perform type interpolation between int values. */
public class IntEvaluator implements TypeEvaluator<Integer> {
public Integer evaluate(float fraction, Integer startValue, Integer endValue) {
return (int)(startValue + fraction * (endValue - startValue));
}
}

FloatEvaluator 源碼

public Float evaluate(float fraction, Number startValue, Number endValue) {
return startValue.floatValue() + fraction * (endValue.floatValue() - startValue.floatValue());
}

ArgbEvaluator 源碼

/** integer values that represent ARGB colors. */
public class ArgbEvaluator implements TypeEvaluator {
/**
* This function returns the calculated in-between value for a color given integers that represent
* the start and end values in the four bytes of the 32-bit int. Each channel is separately單獨的
* linearly interpolated and the resulting calculated values are recombined into the return value.
* @param fraction The fraction from the starting to the ending values
* @param startValue A 32-bit int value representing colors in the separate bytes of the parameter
* @param endValue A 32-bit int value representing colors in the separate bytes of the parameter
* @return A value that is calculated to be the linearly interpolated result, derived by separating
* the start and end values into separate color channels and interpolating each one separately,
* recombining the resulting values in the same way.
*/
public Object evaluate(float fraction, Object startValue, Object endValue) {
int startInt = (Integer) startValue;
int startA = (startInt >> 24) & 0xff;
int startR = (startInt >> 16) & 0xff;
int startG = (startInt >> 8) & 0xff;
int startB = startInt & 0xff;

int endInt = (Integer) endValue;
int endA = (endInt >> 24) & 0xff;
int endR = (endInt >> 16) & 0xff;
int endG = (endInt >> 8) & 0xff;
int endB = endInt & 0xff;

return (int)((startA + (int)(fraction * (endA - startA))) << 24) |
(int)((startR + (int)(fraction * (endR - startR))) << 16) |
(int)((startG + (int)(fraction * (endG - startG))) << 8) |
(int)((startB + (int)(fraction * (endB - startB))));
}
}

自定義TypeEvaluator實現拋物線效果

自定義TypeEvaluator時傳入的泛型可以根據自己的需求,自己設計個Bean。
為了以不同的函數分別設置x和y的位置,我們自定義的TypeEvaluator傳入的泛型為PointF對象,每次根據當前時間返回一個PointF對象,PointF中的x、y代表View當前的位置,然后在監聽動畫繪制過程時更新UI。

自定義TypeEvaluator

public class PointFEvaluator implements TypeEvaluator<PointF> {
    @Override
    public PointF evaluate(float fraction, PointF startValue, PointF endValue) {
        //只要能保證:當fraction=0時返回值為startValue,並且當fraction=1時返回值為endValue,就是一個比較合理的函數
        PointF pointF = new PointF();
        pointF.x = startValue.x + fraction * (endValue.x - startValue.x);// x方向勻速移動
        pointF.y = startValue.y + fraction * fraction * (endValue.y - startValue.y);// y方向拋物線加速移動
        return pointF;
    }
}

在Activity中的使用

// 自定義TypeEvaluator實現拋物線動畫效果
public class TypeEvaluatorActivity extends Activity {
    private ImageView iv_src;
    private boolean b = true;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        getWindow().addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);//全屏
        requestWindowFeature(Window.FEATURE_NO_TITLE);//取消標題欄

        Bitmap bitmap = Bitmap.createBitmap(20, 20, Bitmap.Config.ARGB_8888);
        Canvas canvas = new Canvas(bitmap);
        Paint paint = new Paint();
        paint.setColor(Color.RED);
        paint.setAntiAlias(true);
        paint.setDither(true);
        canvas.drawCircle(10, 10, 10, paint);

        iv_src = new ImageView(this);
        iv_src.setImageBitmap(bitmap);
        setContentView(iv_srcnew LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT));
    }
    @Override
    public boolean onTouchEvent(MotionEvent event) {
        if (event.getActionMasked() == MotionEvent.ACTION_DOWN) {
            b = !b;
            Point point = new Point();
            ((WindowManager) getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay().getSize(point);

            ValueAnimator animator = new ValueAnimator().setDuration(1000);
            //通過new創建的ValueAnimator要明確的setObjectValues和setEvaluator,並且一定要先setObjectValues,再setEvaluator
            if (b) animator.setObjectValues(new PointF(0, 0)new PointF(point.x - iv_src.getWidth(), point.y - iv_src.getHeight()));
            else animator.setObjectValues(new PointF(0, point.y - iv_src.getHeight())new PointF(point.x - iv_src.getWidth(), 0));
            animator.setEvaluator(new PointFEvaluator());//PointFEvaluator為自定義的估值器,其實就是用來封裝你需要的數據用的
            animator.addUpdateListener(new AnimatorUpdateListener() {
                @Override
                public void onAnimationUpdate(ValueAnimator animation) {
                    PointF point = (PointF) animation.getAnimatedValue();
                    iv_src.setX(point.x);
                    iv_src.setY(point.y);
                }
            });
            animator.start();
        }
        return super.onTouchEvent(event);
    }
}


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM