Android自定义View的动画实现方法

最近,在项目中需要实现一个柱状图,并在刷新柱状图的时候有一个动画(柱状图的柱子动态的画出来)。
实现柱状图常用的方法就是,通过继承View类,复写onDraw()方法,根据产品的需求在onDraw()方法里面画相应的矩形(drawRect方法)、文本(drawText方法)等。实现柱状图的难点在根据实际业务的需要计算每个柱子的位置。
下面详细介绍实现自定义View动画的方法,笔者在实现柱状图动画的时候试验了两种方法:
1.第一种方法,在绘制方法中,通过延时一个固定时间调用invalidate()方法,再继续绘制View实现动画效果,代码如下:

    private int mIndex = 0;
    private void drawBar(Canvas canvas) {
        mPaint.setStyle(Paint.Style.FILL);

        for (BarItemInfoBean tempBarPosition : mBarInfoList) {


            PointF upperLeftPoint = tempBarPosition.getUpperLeftPoint();
            PointF lowerRightPoint = tempBarPosition.getLowerRightPoint();

            float left = upperLeftPoint.x;
            float top = upperLeftPoint.y;
            float right = lowerRightPoint.x;
            float bottom = lowerRightPoint.y;

            float delta = (lowerRightPoint.y - upperLeftPoint.y) / 10;          
            top = Math.max(lowerRightPoint.y - (mIndex + 1) * delta, upperLeftPoint.y);

            canvas.drawRect(left, top, right, bottom, mPaint);
        }

        mIndex++;

        if (mIndex < 10) { //通过10次延迟绘制实现动画效果
            postDelayed(new Runnable() {
                @Override
                public void run() {
                    invalidate();
                }
            }, 30);
        }
    }

2.第二种方法,通过属性动画实现动画效果
首先自定义一个动画类,在类中创建一个动画属性的变量(mPhaseY ),而且必须为这个变量设置get 和 set函数,在创建ObjectAnimator对象时使用这个属性。

public class ChartAnimator {

    private ValueAnimator.AnimatorUpdateListener mListener;

    public ChartAnimator() {

    }

    public ChartAnimator(ValueAnimator.AnimatorUpdateListener listener) {
        mListener = listener;
    }

    protected float mPhaseY = 1f;

    public void animateY(int durationMillis) {

        if (android.os.Build.VERSION.SDK_INT < 11)
            return;

        ObjectAnimator animatorY = ObjectAnimator.ofFloat(this, "phaseY", 0f, 1f);
        animatorY.setDuration(durationMillis);
        animatorY.addUpdateListener(mListener);
        animatorY.start();
    }

    public float getPhaseY() {
        return mPhaseY;
    }

    public void setPhaseY(float phase) {
        mPhaseY = phase;
    }

}

然后在自定义的柱状图里面实例化一个ChartAnimator对象,在onDraw()方法里面画柱子时,柱子的高度需要依赖ChartAnimator对象里动画属性(mPhaseY )的返回值。

    private ChartAnimator mAnimator = new ChartAnimator();  
    private void drawBar(Canvas canvas) {
        mPaint.setStyle(Paint.Style.FILL);

        float phaseY = mAnimator.getPhaseY();

        for (BarItemInfoBean tempBarPosition : mBarInfoList) {


            PointF upperLeftPoint = tempBarPosition.getUpperLeftPoint();
            PointF lowerRightPoint = tempBarPosition.getLowerRightPoint();

            float left = upperLeftPoint.x;
            float top = upperLeftPoint.y;
            float right = lowerRightPoint.x;
            float bottom = lowerRightPoint.y;

            top = lowerRightPoint.y - (lowerRightPoint.y - upperLeftPoint.y) * phaseY;

            canvas.drawRect(left, top, right, bottom, mPaint);
        }
    }


    public void animateY(int durationMillis) {
        mAnimator.animateY(durationMillis);
    }

两种方法比较:
第一种方法,实现简单,在Android3.0以下的sdk上也可以实现,但是动画效果不如第二种方法好;
第二种方法,实现起来比较复杂,在Android3.0以上的sdk上才能使用,优点是可以很好的控制动画效果(例如动画持续时间、加速度、减速度等),而且方便扩展。

你可能感兴趣的:(Android开发总结)