Android自定义View——贝塞尔曲线实现水波纹效果

效果图

贝塞尔曲线

我们使用到的是Path类的quadTo(x1, y1, x2, y2)方法,属于二阶贝塞尔曲线,使用一张图来展示二阶贝塞尔曲线,这里的(x1,y1)是控制点,(x2,y2)是终止点,起始点默认是Path的起始点(0,0)

原理分析

1、通过for循环画出两个波纹,需要波纹的-mWL点、-3/4 * mWL点、-1/2 * mWL、-1/4 * mWL四个点,通过path的quadTo画出
2、接着通过ValueAnimator对offset递增,实现平移效果,并无限重复

实现一次循环波纹,红点为贝塞尔坐标:

实现无限次循环波纹:

接下来在波纹下方的空白处画上一个矩形:

实现步骤

1、初始化变量

//波浪画笔
private Paint mPaint;
//测试红点画笔
private Paint mCyclePaint;

//波浪Path类
private Path mPath;
//一个波浪长度
private int mWaveLength = 1000;
//波纹个数
private int mWaveCount;
//平移偏移量
private int mOffset;
//波纹的中间轴
private int mCenterY;

//屏幕高度
private int mScreenHeight;
//屏幕宽度
private int mScreenWidth;

2、初始化画笔

public WaveView(Context context, AttributeSet attrs) {
    super(context, attrs);
    mPath = new Path();
    mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
    mPaint.setColor(Color.LTGRAY);
    mPaint.setStyle(Paint.Style.FILL_AND_STROKE);
    setOnClickListener(this);
    //用来绘制测试红点
    mCyclePaint = new Paint(Paint.ANTI_ALIAS_FLAG);
    mCyclePaint.setColor(Color.RED);
    mCyclePaint.setStyle(Paint.Style.FILL_AND_STROKE);
}

3、获取宽和高

@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
    super.onSizeChanged(w, h, oldw, oldh);
    mScreenHeight = h;
    mScreenWidth = w;
    //加1.5:至少保证波纹有2个,至少2个才能实现平移效果
    mWaveCount = (int) Math.round(mScreenWidth / mWaveLength + 1.5);
    mCenterY = mScreenHeight / 2;
}

4、绘制水波纹

@Override
protected void onDraw(Canvas canvas) {
    super.onDraw(canvas);
    mPath.reset();
    //移到屏幕外最左边
    mPath.moveTo(-mWaveLength + mOffset, mCenterY);
    for (int i = 0; i < mWaveCount; i++) {
        //正弦曲线
        mPath.quadTo((-mWaveLength * 3 / 4) + (i * mWaveLength) + mOffset, mCenterY + 60, (-mWaveLength / 2) + (i * mWaveLength) + mOffset, mCenterY);
        mPath.quadTo((-mWaveLength / 4) + (i * mWaveLength) + mOffset, mCenterY - 60, i * mWaveLength + mOffset, mCenterY);
        //贝塞尔坐标,测试红点
        canvas.drawCircle((-mWaveLength * 3 / 4) + (i * mWaveLength) + mOffset, mCenterY + 60, 5, mCyclePaint);
        canvas.drawCircle((-mWaveLength / 2) + (i * mWaveLength) + mOffset, mCenterY, 5, mCyclePaint);
        canvas.drawCircle((-mWaveLength / 4) + (i * mWaveLength) + mOffset, mCenterY - 60, 5, mCyclePaint);
        canvas.drawCircle(i * mWaveLength + mOffset, mCenterY, 5, mCyclePaint);
    }
    //填充矩形
    mPath.lineTo(mScreenWidth, mScreenHeight);
    mPath.lineTo(0, mScreenHeight);
    mPath.close();
    canvas.drawPath(mPath, mPaint);
}

5、实现平移效果

@Override
public void onClick(View view) {
    ValueAnimator animator = ValueAnimator.ofInt(0, mWaveLength);
    animator.setDuration(1000);
    animator.setRepeatCount(ValueAnimator.INFINITE);
    animator.setInterpolator(new LinearInterpolator());
    animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
        @Override
        public void onAnimationUpdate(ValueAnimator animation) {
            mOffset = (int) animation.getAnimatedValue();
            postInvalidate();
        }
    });
    animator.start();
}

6、源码下载

水波纹View下载

评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

许英俊潇洒

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值