天天看點

android 使用貝塞爾曲線實作“波浪”效果思路解析

首先對于貝塞爾曲線是什麼我就不在叙述了。各位可能對于貝塞爾曲線已經不陌生了。

先看下效果圖

這是一張靜态圖,實際上是動态的!!!

android 使用貝塞爾曲線實作“波浪”效果思路解析

要實作“波浪”效果,先介紹一下二階貝塞爾曲線的幾個方法:

1:moveto 方法,就是設定起點,源碼如下:

public void moveTo(float x, float y) {
        native_moveTo(mNativePath, x, y);
    }
           

2:quadTo方法 x1,y1就是控制點的坐标; x2,y2就是終點的坐标,源碼如下:

public void quadTo(float x1, float y1, float x2, float y2) {
        isSimplePath = false;
        native_quadTo(mNativePath, x1, y1, x2, y2);
    }
           

3:lineTo(x1,y1)方法我需要也别解釋一下:就是連接配接起點和終點;不說的話,這個可能會坑到很多人。如下如所示,

android 使用貝塞爾曲線實作“波浪”效果思路解析

一般來說 我們是起點到(x1,y1),然後是(x1,y1)到終點,如果是這樣的話 就錯了!

注意:lineTo繪制這兩條線的先後順序是:終點到(x1,y1),然後才是(x1,y1)到起點!!!!!!

同理兩個LineTo的話就是:終點到(x2,y2)然後是(x2,y2)到(x1,y1),最後是(x1,y1)到終點。這個很重要!!!

好了 這是方法,然後看思路: 我們畫兩個波浪,然後一個占滿螢幕,一個在螢幕外,然後每次更新width的值,height的值不變,然後循環。大體思路就是這樣。

如下圖:

android 使用貝塞爾曲線實作“波浪”效果思路解析

到這裡,我想應該就可以自己寫出代碼了。

附上整體代碼:

package com.app.test.beisaierproject;

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.PixelFormat;
import android.util.AttributeSet;
import android.util.Log;
import android.view.SurfaceHolder;
import android.view.SurfaceView;

/**
 * Created by ${liumegnqiang} on 2017/5/19.
 */

public class MyBeiSaiErView extends SurfaceView implements SurfaceHolder.Callback{
    private SurfaceHolder surfaceHolder;
    public MyBeiSaiErView(Context context) {
        super(context);
    }

    public MyBeiSaiErView(Context context, AttributeSet attrs) {
        super(context, attrs);
        surfaceHolder = getHolder();
        surfaceHolder.setFormat(PixelFormat.TRANSLUCENT);
        surfaceHolder.addCallback(this);
    }

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

    @Override
    public void surfaceCreated(SurfaceHolder holder) {
        new Thread(new MyThread()).start();
    }

    @Override
    public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {

    }

    @Override
    public void surfaceDestroyed(SurfaceHolder holder) {

    }

    public class MyThread extends Thread{
        @Override
        public void run() {
            super.run();
            /**
             * 修改波浪的寬度
             */
            int measuredWidth = getMeasuredWidth();
            /**
             * 修改波浪的高度
             */
            int measuredHeight = getMeasuredHeight();
            /**
             * 總共平移的間隔
             */
            int totalWidth = ;
            while (true){
                try {
                    sleep();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                Canvas canvas = surfaceHolder.lockCanvas();
                try {
                    canvas.drawColor(Color.GRAY);

                    Paint paint = new Paint();
                    paint.setColor(Color.BLUE);
                    paint.setAntiAlias(true);
                    paint.setStyle(Paint.Style.FILL);

                    Path path = new Path();

                    path.moveTo(-measuredWidth + totalWidth,measuredHeight/);
                    path.quadTo(-measuredWidth * / + totalWidth,measuredHeight * /,
                            -measuredWidth/+ totalWidth,measuredHeight/);
                    path.quadTo(-measuredWidth / + totalWidth,measuredHeight*/,
                            + totalWidth,measuredHeight/);
                    path.quadTo(measuredWidth / + totalWidth,measuredHeight*/,
                            measuredWidth/+ totalWidth,measuredHeight/);
                    path.quadTo(measuredWidth * / + totalWidth,measuredHeight*/,
                            measuredWidth+ totalWidth,measuredHeight/);

                    path.lineTo(measuredWidth+ totalWidth,measuredHeight);
                    path.lineTo(-measuredWidth+ totalWidth,measuredHeight);
                    path.close();

                    canvas.drawPath(path,paint);

                    totalWidth += ;

                    if(totalWidth > getMeasuredWidth()){
                        totalWidth = ;
                    }

                }catch (Exception e){
                    e.printStackTrace();
                }finally {
                    surfaceHolder.unlockCanvasAndPost(canvas);
                }
            }

        }
    }
}
           

這裡我用的是surfaceview,因為在繪制動态圖的方面,surfaceview比view性能是好的。當然你也可以加上雙緩沖技術。

最後附上源碼位址:http://download.csdn.net/detail/lmq121210/9846701

源碼下載下傳之後直接能用的。

繼續閱讀