adnroid贝塞尔实现自定义水波View

贝塞尔曲线

贝塞尔是数学中的一个定义轨迹的东西,由起点、终点、控制点组成。其中控制点可以是一个或者多个,贝塞尔原理在android中可以实现很多有趣的动画效果。下面我就自定义用贝塞尔实现一个水波纹效果的自定义View。

原理图
adnroid贝塞尔实现自定义水波View_第1张图片

最终效果图
adnroid贝塞尔实现自定义水波View_第2张图片

直接贴代码


public class WaveView extends View {

    /*****画水波纹画笔*****/
    private Paint mPaint;
    /******水波路径*******/
    private Path mPath;
    /******水波个数 注意水波个数至少两个********/
    private int mWaveCount=3;
    /*****view宽********/
    private float mWidth;
    /*****view高******/
    private float mHeight;
    /*****一个水波周期的宽度*********/
    private float mWaveWidth;
    /******贝塞尔控制点 Y轴偏移量 浪高*******/
    private float mOffsetY=50;
    /******水波X轴平移量*******/
    private float mOffsetX;
    /****水波水平线Y轴值*****/
    private float mCenterY;
    /*****一个水波周期的4分之一宽度********/
    private float mSkip;
    /*****水波平移动画*********/
    private ValueAnimator mValueAnimator;
    /*****水波颜色*********/
    private int mWaveColor=Color.BLUE;


    public WaveView(Context context) {
        super(context);
        init();
    }

    public WaveView(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
        init();
    }

    public WaveView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init();
    }


    @Override
    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
        super.onSizeChanged(w, h, oldw, oldh);
        mWidth=w;
        mHeight=h;
        mCenterY=mHeight / 2f;
        mWaveWidth=mWidth / (mWaveCount-1);//因为在屏幕左边屏幕外有一个周期的水波,所以该处应该减1
        mSkip=mWaveWidth / 4;
        startAnimator();
    }

    private void init(){
        mPaint=new Paint(Paint.ANTI_ALIAS_FLAG);
        mPaint.setAntiAlias(true);
        mPaint.setStyle(Paint.Style.FILL_AND_STROKE);
        mPaint.setColor(mWaveColor);
        mPaint.setStrokeWidth(5f);
        mPath=new Path();
    }


    private void startAnimator(){
        mValueAnimator=ValueAnimator.ofFloat(0,mWaveWidth);
        mValueAnimator.setDuration(1*1000);
        mValueAnimator.setRepeatCount(ValueAnimator.INFINITE);
        mValueAnimator.setInterpolator(new LinearInterpolator());
        mValueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator valueAnimator) {
                mOffsetX=(float)valueAnimator.getAnimatedValue();
                postInvalidate();
            }
        });
        mValueAnimator.start();
    }


    @Override
    protected void onDraw(Canvas canvas) {
       // super.onDraw(canvas);
        canvas.drawColor(Color.GRAY);
        mPath.reset();
        mPath.moveTo(-mWaveWidth,mCenterY);
        for(int i=0;i
在上面代码的基础上还可以实现圆形的进度效果
adnroid贝塞尔实现自定义水波View_第3张图片

代码如下

public class WaveView extends View {

    /*****画水波纹画笔*****/
    private Paint mPaint;
    /******水波路径*******/
    private Path mPath;
    /******水波个数 注意水波个数至少两个********/
    private int mWaveCount=3;
    /*****view宽********/
    private float mWidth;
    /*****view高******/
    private float mHeight;
    /*****一个水波周期的宽度*********/
    private float mWaveWidth;
    /******贝塞尔控制点 Y轴偏移量 浪高*******/
    private float mOffsetY=50;
    /******水波X轴平移量*******/
    private float mOffsetX;
    /****水波水平线Y轴值*****/
    private float mCenterY;
    /*****一个水波周期的4分之一宽度********/
    private float mSkip;
    /*****水波平移动画*********/
    private ValueAnimator mValueAnimatorX;
    /*****水波颜色*********/
    private int mWaveColor=Color.BLUE;

    /*****底部水波纹bitmap*****/
    private Bitmap mBitmap;
    /******XFerMode画笔*******/
    private Paint  mXferModePaint;
    /*****画组合Bitmap的画布*******/
    private Canvas mCanvas;
    /*****前景过滤bitmap********/
    private Bitmap mForegroundBitmap;
    /******前景bitmap的颜色*****/
    private int mForegroundColor=Color.WHITE;

    /*****水波纹Y轴动画******/
    private ValueAnimator mValueAnimatorY;
    /*****水平移动周期时间******/
    private int mTimeX=1000;
    /*****Y轴移动周期时间********/
    private int mTimeY=15*1000;

    public WaveView(Context context) {
        super(context);
        init();
    }

    public WaveView(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
        init();
    }

    public WaveView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init();
    }
   private void init(){
        mPaint=new Paint(Paint.ANTI_ALIAS_FLAG);
        mPaint.setAntiAlias(true);
        mPaint.setStyle(Paint.Style.FILL_AND_STROKE);
        mPaint.setColor(mWaveColor);
        mPaint.setStrokeWidth(5f);

        mXferModePaint=new Paint(Paint.ANTI_ALIAS_FLAG);
        mXferModePaint.setAntiAlias(true);
        mXferModePaint.setStyle(Paint.Style.FILL_AND_STROKE);
        mXferModePaint.setStrokeWidth(5f);
        mXferModePaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_ATOP));

        mPath=new Path();
    }

    @Override
    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
        super.onSizeChanged(w, h, oldw, oldh);
        mWidth=w;
        mHeight=h;
        mCenterY=mHeight / 1f;
        mWaveWidth=mWidth / (mWaveCount-1);//因为在屏幕左边屏幕外有一个周期的水波,所以该处应该减1
        mSkip=mWaveWidth / 4;
        mBitmap=Bitmap.createBitmap((int)mWidth,(int)mHeight, Bitmap.Config.ARGB_8888);
        mCanvas=new Canvas(mBitmap);
        mForegroundBitmap=getForegroundBitmap((int)mWidth,(int)mHeight);
        startAnimator();
    }

 


    private void startAnimator(){
        mValueAnimatorX=ValueAnimator.ofFloat(0,mWaveWidth);
        mValueAnimatorX.setDuration(mTimeX);
        mValueAnimatorX.setRepeatCount(ValueAnimator.INFINITE);
        mValueAnimatorX.setInterpolator(new LinearInterpolator());
        mValueAnimatorX.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator valueAnimator) {
                mOffsetX=(float)valueAnimator.getAnimatedValue();
                postInvalidate();
            }
        });
        mValueAnimatorX.start();


        mValueAnimatorY=ValueAnimator.ofFloat(mHeight,0);
        mValueAnimatorY.setDuration(mTimeY);
        mValueAnimatorY.setRepeatCount(ValueAnimator.INFINITE);
        mValueAnimatorY.setInterpolator(new LinearInterpolator());
        mValueAnimatorY.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator valueAnimator) {
                mCenterY=(float)valueAnimator.getAnimatedValue();
            }
        });
        mValueAnimatorY.start();
    }


    @Override
    protected void onDraw(Canvas canvas) {
       // super.onDraw(canvas);
        mPaint.setColor(mWaveColor);
        canvas.drawColor(Color.GRAY);
        mPath.reset();
        mPath.moveTo(-mWaveWidth,mCenterY);
        for(int i=0;i

你可能感兴趣的:(adnroid贝塞尔实现自定义水波View)