贝塞尔曲线可以通过设置很少的控制点,来绘制想要的平滑的曲线。下面是我使用贝塞尔曲线实现的水波纹效果,直接贴出关键代码
public class BezierView extends View {
private static final String TAG = "BezierView";
private Paint mPaint;
private Path mBezierPath;
private ValueAnimator valueAnimator;
private static final int waveWidth = 160;
private static final int waveHeight = 80;
int offset = 0;
public BezierView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
mPaint = new Paint();
mPaint.setAntiAlias(true);
mPaint.setStyle(Paint.Style.FILL);
mPaint.setColor(Color.YELLOW);
mBezierPath = new Path();
valueAnimator = ValueAnimator.ofInt(0,waveWidth*2); //这里需要设置两个波形的长度,这样上旋和下旋才能完整显示
valueAnimator.setDuration(1200);
valueAnimator.setRepeatCount(-1); //设置一直重复
valueAnimator.setInterpolator(new LinearInterpolator()); //这里设置线性插值器,保证平滑不卡顿
valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator valueAnimator) {
int value = (int) valueAnimator.getAnimatedValue();
offset = value;
Log.d(TAG,"offset:" + offset);
postInvalidate();
}
});
valueAnimator.start();
}
然后在ondraw里面去绘制贝塞尔曲线
@Override
protected void onDraw(Canvas canvas) {
mBezierPath.reset();
int startx = offset - waveWidth*2;
//设置起始点
mBezierPath.moveTo(startx,getHeight()/2 -100);
// //获取贝塞尔曲线路径,这里传入的是控制点和终点,都是绝对的坐标值
// mBezierPath.quadTo(startx + waveWidth/2 ,mControlPoint.y,offset,mEndPoint.y);
for (int i = -waveWidth ; i <= getWidth() ; i += waveWidth*2){
//这里是相对于上一个曲线的终点位置,添加控制点和终点,值都是相对坐标值。这是一个完整的波形
mBezierPath.rQuadTo(waveWidth/2,waveHeight/2,waveWidth,0);
mBezierPath.rQuadTo(waveWidth/2,-waveHeight/2,waveWidth,0);
}
//封闭曲线
mBezierPath.lineTo(getWidth(),getHeight());
mBezierPath.lineTo(0,getHeight());
mBezierPath.close();
//绘制贝塞尔曲线
canvas.drawPath(mBezierPath,mPaint);
}
实现的效果如下: