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() {
                @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]

你可能感兴趣的:(Android开发,Android开发之动画)