开发悬浮球SDK之自定义view(流量球)上篇 — 水波纹(波浪线)

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_36791265/article/details/78059161

本人开发悬浮球SDK大致流程及过程中遇到的问题和解决方法我会写到我的博客中。

(关于Paint 类,Path类,Canvas类相关具体详解,请您拉到本博客下方,点击链接方便您学习哦!)

自定义view的核心方法 onMeasure(int widthMeasureSpec,int heightMeasureSpec),onLayout(boolean changed,int left,int top,int right,int bottom),onDraw(Canvas  canvas)。

invalidate()   是进行重绘 ,每次执行时会调用onDraw()方法。

初始时流量球界面的实现效果上面要求我流量球有水波纹效果,之后改成圆形图片背景(地址:裁剪图片过程),文字嵌入其中。这些之中所面对的问题就是:水波纹效果实现,圆形图片剪切。


水波纹效果:其中核心就是 sin、cos 函数,通过此函数可以通过Paht类 画出水波纹的流动效果,如果你对三角函数不太了解,可以学习一下。(在网上没找到较好的三角函数介绍的网址,您只能自己查一下书籍了)

     简单版代码如下:   这是简单的波纹线的绘制。用来跟朋友们解释水波纹的核心原理。

     y = Asin(Wx + b)+h ;以左上角为中心x表示其水平位置,y表示在x处当前点的竖直方向位置。W决定震动周期,W 越大波浪周期越短(反比)。

A是震动幅度决定Y值大小(正比), b是初相,决定初始时x轴上平移位置,h决定y的位置y轴 ,本例使用正弦函数;


public class View2 extends View {
    Context context ;
    Paint linePaint1;
    Paint linePaint2;
    Canvas canvas1;
    Path path1;
    Path path2;

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

    public View2(Context context, AttributeSet attrs) {
        super(context, attrs);
        this.context = context;
        init();
    }

    public View2(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        this.context = context;
        init();
    }


    private void init() {
        linePaint1 = new Paint();//Paint 类的详解,请您拉到本博客下方
        linePaint1.setColor(Color.RED);
        linePaint1.setAntiAlias(true);//设置抗锯齿,线条更平滑
        linePaint1.setStyle(Paint.Style.STROKE);//paint.Style.stroke 设置画笔样式为空心。例如:画的圆是空心的
        linePaint1.setStrokeWidth(3);// 线宽
        linePaint2 = new Paint();
        linePaint2.setColor(Color.BLUE);
        linePaint2.setAntiAlias(true);
        linePaint2.setStyle(Paint.Style.STROKE);
        linePaint2.setStrokeWidth(3);
        path1= new Path();//Path 类的详解,请您拉到本博客下方
        path2= new Path();
        canvas1 = new Canvas();// canvas 类的详解,请您拉到本博客下方
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        setMeasuredDimension(widthMeasureSpec,heightMeasureSpec);
    }
    int w ;
    int h  = height / 2;
    double W = 15;
    int A = 8;
    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        //画出波浪条纹  sin、cos
        // Math.sin();
        canvas1 = canvas;
        canvas1.drawCircle(width/2,height/2,width/2,linePaint1);
        postDelayed(new LineRunnable(),50);

    }


    private class  LineRunnable implements Runnable {

        @Override
        public void run() {
            path1.reset();
            path2.reset();
            path1.moveTo(0,h);
            path2.moveTo(0,h);
            w+=5;
            if(w> (width-5)*2){
                w = 0;
            }
            for(int i = 5;i<width;i++){
//            y = Asin(Wx + b)+h
                path1.lineTo(i, h + (float) (A*Math.sin(Math.PI*(i+w) / width)));// 这里我们要想弧线尽量平滑那么就将周期尽量变长,所以W的值尽可能小,
                path2.lineTo(i,h - (float) (A*Math.sin(Math.PI*(i+w) / width)));
            }
            //path1.close();
            canvas1.drawPath(path1, linePaint1);
            canvas1.drawPath(path2, linePaint2);
            invalidate();
        }
    }
}

下面是完整版的波浪水纹():


此水波纹效果颜色我设置为RED和BLUE,高度设置为height的一半,linePaint1和linePaint2 的样式属性设置为默认,只将边框circlePaint设置为Paint.Style.STROKE,线宽为3所以 对比简单水波纹,我们需要将i 的初始值设置为线宽3(i是path的第一个参数就是横坐标),您如果想要波浪能跟随高度而变化,那么不仅仅要调节波浪本身高度 h 的参数,还要同步调节波浪线的初始和结束的位置。由于公司改变了SDK的样式要求,波浪线的绘制就到这里,不过今后随着我学习深入会补充随高度变化的水波纹效果以及更绚丽的效果。

public class View1 extends View {
    Context context ;
    Paint linePaint1;
    Paint linePaint2;
    Paint circlePaint;
    Canvas canvas1;
    Path path1;
    Path path2;
    RectF rectF;

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

    public View1(Context context, AttributeSet attrs) {
        super(context, attrs);
        this.context = context;
        init();
    }

    public View1(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        this.context = context;
        init();
    }


    private void init() {
        linePaint1 = new Paint();//Paint 类的详解,请您拉到本博客下方
        linePaint1.setColor(Color.RED);
        linePaint1.setAntiAlias(true);//设置抗锯齿,线条更平滑
//        linePaint1.setStyle(Paint.Style.STROKE);//paint.Style.stroke 设置画笔样式为空心。例如:画的圆是空心的
//        linePaint1.setStrokeWidth(3);// 线宽
        linePaint2 = new Paint();
        linePaint2.setColor(Color.BLUE);
        linePaint2.setAntiAlias(true);
//        linePaint2.setStyle(Paint.Style.STROKE);
//        linePaint2.setStrokeWidth(3);

        circlePaint = new Paint();
        circlePaint.setColor(Color.BLACK);// 设置黑色边框,是为了您观察更清楚
        circlePaint.setAntiAlias(true);//设置抗锯齿,线条更平滑
        circlePaint.setStyle(Paint.Style.STROKE);//paint.Style.stroke 设置画笔样式为空心。例如:画的圆是空心的
        circlePaint.setStrokeWidth(3);// 线宽

        rectF = new RectF(3,3,width+3,height+3);//这里设置矩形,是用来画圆的,让界面出现一个实心的半圆效果,结合弧线会展示出实心波浪的效果

        path1= new Path();//Path 类的详解,请您拉到本博客下方
        path2= new Path();
        canvas1 = new Canvas();// canvas 类的详解,请您拉到本博客下方
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        setMeasuredDimension(widthMeasureSpec,heightMeasureSpec);
    }
    int w ;
    int h  = height / 2;
    double W = 15;
    int A = 8;
    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        //画出波浪条纹  sin、cos
        // Math.sin();
        canvas1 = canvas;
        canvas1.drawCircle(width/2+3,height/2+3,width/2,circlePaint);
        postDelayed(new LineRunnable(),50);

    }


    private class  LineRunnable implements Runnable {

        @Override
        public void run() {
            path1.reset();
            path2.reset();

            path1.addArc(rectF,0,180);// 参数1 是矩形变量,2 是初始弧度,3 是结束弧度 (我只是简单介绍,具体的有关弧度及path类详解请您拉到本博客下方)
            path2.addArc(rectF,0,180);

            w+=3;//w 值设置为外圆线宽 3
            if(w> (width-3)*2){
                w = 0;
            }
            for(int i = 3;i<width+3;i++){// 水波纹最后一个位置是(width + 线宽)
//            y = Asin(Wx + b)+h
                path1.lineTo(i, h + (float) (A*Math.sin(Math.PI*(i+w) / width)));
                path2.lineTo(i,h - (float) (A*Math.sin(Math.PI*(i+w) / width)));
            }
            path1.close();//闭合路径,使得颜色完全填充。
            path2.close();

            canvas1.drawPath(path1, linePaint1);
            canvas1.drawPath(path2, linePaint2);
            invalidate();
        }
    }
}

这只是水波纹绘制的其中一种方法,还有一个更好理解的是通过赛贝尔曲线:核心方法是path.quadTo(); 四个参数前俩是途经的点坐标,后俩是终点的坐标。通过设定多个点,可以展现出波浪线的效果。


以下是从网上找的介绍Paint 类、Path类、Canvas类的好的网站(方便您学习哦!):

Paint : http://blog.csdn.net/abcdef314159/article/details/51720686

Path : http://blog.csdn.net/u012702547/article/details/52454406 , http://www.jianshu.com/p/f1e4fc2feb25 , path.ArcTo()弧度解释

Canvas : http://www.jcodecraeer.com/a/anzhuokaifa/androidkaifa/2012/1212/703.html

猜你喜欢

转载自blog.csdn.net/qq_36791265/article/details/78059161
今日推荐