前言:
好像是从简书看到一个IOS的双曲线波浪的动画,刚好最近把Cavans重新复习了一遍,那么就用这个来巩固好了,而且这个效果确实挺好玩的。如果大家对android中的三次贝塞尔曲线不太理解,对API也不太熟的,可以去这个博客看看[置顶] Android自定义控件三部曲文章索引,这是我读过总结的最详细的博文,很适合摸索阶段和温习阶段去阅读,这里感谢启舰大神,非常细致的博文。

上图:

Android波纹动画 安卓波浪动画_API

颜色搭配有点丑,wave的波长也不是很完美,大家将就着看下就是了,看是来看代码好了。

代码通杀一切:
DoubleWaveView

package cjh.doublewave;

import android.animation.ValueAnimator;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Path;
import android.util.AttributeSet;
import android.view.View;
import android.view.animation.LinearInterpolator;

/**
 * Created by chenjiahuan on 16/7/1.
 */
public class DoubleWaveView extends View {

    private Paint mPaint;
    private Path mPath;
    private int width, height;

    private int dx;

    public DoubleWaveView(Context context, int width, int height) {
        super(context);
        this.width = width;
        this.height = height;
        init();
    }

    public DoubleWaveView(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    public DoubleWaveView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }

    private void init() {
        mPath = new Path();
        mPaint = new Paint();
        mPaint.setStyle(Paint.Style.FILL_AND_STROKE);
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        mPath.reset();
        mPaint.setColor(Color.parseColor("#65ff0000"));
        mPath.moveTo(-width + dx, height / 5 * 4);
        for (int i = 0; i < 3; i++) {
            mPath.rQuadTo(width / 4, -70, width / 2, 0);
            mPath.rQuadTo(width / 4, 70, width / 2, 0);
        }
        mPath.lineTo(width, height);
        mPath.lineTo(0, height);
        mPath.close();
        canvas.drawPath(mPath, mPaint);

        mPath.reset();
        mPaint.setColor(Color.parseColor("#6500ff00"));
        mPath.moveTo(-width + dx, height / 5 * 4);
        for (int i = 0; i < 3; i++) {
            mPath.rQuadTo(width / 4, 70, width / 2, 0);
            mPath.rQuadTo(width / 4, -70, width / 2, 0);
        }
        mPath.lineTo(width, height);
        mPath.lineTo(0, height);
        mPath.close();
        canvas.drawPath(mPath, mPaint);

    }

    public void startAnimation() {
        ValueAnimator valueAnimator = ValueAnimator.ofInt(0, width);
        valueAnimator.setDuration(2000);
        valueAnimator.setRepeatCount(ValueAnimator.INFINITE);
        valueAnimator.setInterpolator(new LinearInterpolator());
        valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                dx = (int) animation.getAnimatedValue();
                invalidate();
            }
        });
        valueAnimator.start();
    }
}

先看onDraw部分,其实只需要看其中一个wave的代码就OK了:

mPath.reset();
        mPaint.setColor(Color.parseColor("#65ff0000"));
        mPath.moveTo(-width + dx, height / 5 * 4);
        for (int i = 0; i < 3; i++) {
            mPath.rQuadTo(width / 4, -70, width / 2, 0);
            mPath.rQuadTo(width / 4, 70, width / 2, 0);
        }
        mPath.lineTo(width, height);
        mPath.lineTo(0, height);
        mPath.close();
        canvas.drawPath(mPath, mPaint);

既然是画一条占满屏幕宽度的wave,肯定是使用rQuadTo这个API了,和quadTo的API绝对位置不同的是rQuadTo的参数都是相对位置的值,这个两个API我想还是稍微说下好了,看图:

Android波纹动画 安卓波浪动画_API_02

OK,说完了,有点粗糙和暴力,不过应该能看懂就是了,如果还是不懂,可以看开头介绍的那篇博客。

代码中mPath.moveTo(-width + dx, height / 5 * 4);这一行x轴的起始点不是固定的,dx是跟着属性动画走的,如果不清楚属性动画可以看我的文章Android动画-Property Animation(一),在博文的最后稍微介绍了抛物线的动画,其实就是使用的拦截器,一个道理。

我整个wave的波长其实就是屏幕的宽度,所以我在画wave的时候小小的偷了个懒,因为我知道我想画的wave其实就是屏幕的三倍长,所以循环了三次,如果是不知道自己到底的wave的最终具体波长的可以这么写:

if(int i = -wavewidth; i<= screenwidth + wavewidth; i+=wavewidth ){
}

这里循环的意思,其实就是我从屏幕左侧一个波长的点开始,每次增长一个wave的长度,最后想要到达屏幕右侧一个波长的点。

OK,属性动画这里就不需要多讲了吧,很简单的一个值得变化,另外注意下,在MainActivity中,动态添加的时候需要,设置LayoutParams

private void initWaveView() {
        rootView = (FrameLayout) findViewById(R.id.rootView);
        waveView = new DoubleWaveView(this, width, height);
        FrameLayout.LayoutParams params = new FrameLayout.LayoutParams(width, height);
        rootView.addView(waveView, params);
        waveView.startAnimation();
    }

这样一个很简单的双曲线动画就OK了,当然了我看到的双曲线动画,比这个要精致很多,那是下一篇博客的内容了。