Android中ValueAnimator的使用

寫在前面的話

這個時代,新物種正在生長,新邊疆正在延伸。做別人的小兵,還是做自己的將軍,你選。

前言

  • 今天給大家帶來的是ValueAnimator的相關用法,下面先給大家看下效果圖。

效果圖

這裏寫圖片描述

動畫介紹

這裏我們寫了兩個位移動畫,分別是城市交換動畫和日期位移動畫,下面我們將通過代碼詳細介紹下兩個動畫的具體實現,從而理解valueAnimator的相關使用。

城市交換動畫

  • 左邊城市:startCityTextView
  • 右邊城市:endCityTextView
  • 首先獲取startCityTextView和endCityTextView的x座標,因爲是水平方向的移動。
    1. startX:左邊城市的橫座標
    2. endX:右邊城市的橫座標
    private int startX;
    private int endX;

    private void getLocation() {
        int[] startLocation = new int[2];
        startCityTextView.getLocationOnScreen(startLocation);
        int[] endLocation = new int[2];
        endCityTextView.getLocationOnScreen(endLocation);
        startX = startLocation[0];
        endX = endLocation[0];
    }

左邊城市動畫

  • 移動距離
final int moveX = endX - startX + endCityTextView.getWidth() - startCityTextView.getWidth();
  • 動畫代碼
ValueAnimator startCityAnimation = ValueAnimator.ofInt(0, moveX).setDuration(500);
        startCityAnimation.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                int value = (int) animation.getAnimatedValue();
                startCityTextView.layout(startX + value, startCityTextView.getTop(), startX + value + startCityTextView.getWidth(), startCityTextView.getBottom());
            }
        });
        startCityAnimation.start();

右邊城市動畫

  • 移動距離
int rightMoveX = endX - startX;
  • 動畫代碼
ValueAnimator endCityAnimator = ValueAnimator.ofInt(0, rightMoveX).setDuration(500);
        endCityAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                int value = (int) animation.getAnimatedValue();
                endCityTextView.layout(endX - value, endCityTextView.getTop(), endX + endCityTextView.getWidth() - value, endCityTextView.getBottom());
            }
        });
        endCityAnimator.start();

調換view位置

最後需要在動畫結束後調換view的位置, 使startCityTextView變爲endCityTextView,這樣下次動畫執行時位置座標才正確。

endCityAnimator.addListener(new Animator.AnimatorListener() {
            @Override
            public void onAnimationStart(Animator animation) {
            }

            @Override
            public void onAnimationEnd(Animator animation) {
                TextView flagTextView = startCityTextView;
                startCityTextView = endCityTextView;
                endCityTextView = flagTextView;
            }

            @Override
            public void onAnimationCancel(Animator animation) {
            }

            @Override
            public void onAnimationRepeat(Animator animation) {
            }
        });

日期位移動畫

透明度動畫

  • isSingleLine:判斷是點擊的單程還是往返
    1. 單程:透明度由1變到0,通過重寫ObjectAnimator的setEvaluator方法,其中fraction的變化是由0到1
    2. 往返:透明度從0變到1
ObjectAnimator alphaAnimator = ObjectAnimator.ofFloat(rightLayout, View.ALPHA, 0, 1.0f).setDuration(1000);
        if (isSingleLine) {
            alphaAnimator.setEvaluator(new TypeEvaluator<Float>() {
                @Override
                public Float evaluate(float fraction, Float startValue, Float endValue) {
                    return 1 - fraction;
                }
            });
        }
        alphaAnimator.start();

位移動畫

動畫分析:

  • screenWidth 屏幕寬度
    1. 往返:把view從screenWidth+view.getWidth()的位置移動到screenWidth-view.getWidth的位置,移動距離:view.getWidth()
    2. 單程:把view移出到screenWidth和view.getWidth()之和的位置,移動距離:view.getWidth()
  • 獲取屏幕寬度
    private int getScreenWidth() {
        DisplayMetrics displayMetrics = getResources().getDisplayMetrics();
        return displayMetrics.widthPixels;
    }
  • 動畫代碼
ValueAnimator animator = ValueAnimator.ofFloat(0, rightLayout.getWidth()).setDuration(500);
        animator.setEvaluator(isSingleLine ? new ATFlightEvaluator() : new FloatEvaluator());
        animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                float value = (float) animation.getAnimatedValue();
                int screenWidth = getScreenWidth();
                rightLayout.layout(screenWidth - (int) value, rightLayout.getTop(), screenWidth + rightLayout.getWidth() - (int) value, rightLayout.getBottom());
            }
        });
        animator.start();


  • ATFlightEvalutor

這裏isSingleLine時我們設置其Evaluator爲我們自定義的ATFlightEvalutor,實現TypeEvaluator接口並重寫其evaluate方法,這樣我們獲取到動畫變化中的value值就是由view.getWidth()—>0變化的。
  1. startValue: 0
  2. endValue: view.getWidth()
  3. fraction: 動畫的變化率0—>1
  4. 其最後返回的值就是我們使用animation.getAnimatedValue()獲取的值。
public class ATFlightEvaluator implements TypeEvaluator<Float> {

    @Override
    public Float evaluate(float fraction, Float startValue, Float endValue) {
        return endValue - fraction * (endValue - startValue);
    }
}

總結

以上就是我們通過valueAnimator實現的兩個小實例,有興趣的童鞋可以研究下代碼,另外有不明白的地方可以在下面留言或者發郵件[email protected]

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章