<com.atsgg.customviewdemo09.WaveView
android:layout_width="match_parent"
android:layout_height="match_parent"/>
private Paint mPaint;// 畫筆對象
private Path mPath;// 路徑對象
private int vWidth, vHeight;// 控件寬高
private float ctrX, ctrY;// 控制點的座標
private float waveY;// 整個Wave頂部兩端點的Y座標,該座標與控制點的Y座標增減幅一致,以及
private float startX, endX;// 整個Wave的左端點,與右端點
private boolean isInc; // 判斷控制點是該坐移還是右移,true爲右移
public WaveView(Context context) {
this(context, null);
}
public WaveView(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public WaveView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
// 實例化畫筆並設置參數
mPaint = new Paint(Paint.ANTI_ALIAS_FLAG | Paint.DITHER_FLAG);
mPaint.setColor(0xFF00796B);
// 實例化路徑
mPath = new Path();
}
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
// 獲取控件的寬高
vWidth = w;
vHeight = h;
// 計算端點Y座標
waveY = 1 / 8F * vHeight;
// 計算控制點Y的座標
ctrY = -1 / 16F * vHeight;
startX = -1 / 4F * vWidth;
endX = 1 / 4F * vWidth + vWidth;
}
@Override
protected void onDraw(Canvas canvas) {
/**
* 設置Path起點
* 注意我將Path的起點設置在了控件的外部看不到的區域
* 如果我們將起點設置在控件左端x=0的位置會使得貝塞爾曲線變得生硬
* 至於爲什麼剛纔我已經說了
* 所以我們稍微讓起點往“外”走點
*/
mPath.moveTo(startX, waveY);
/**
* 以二階曲線的方式通過控制點連接位於控件右邊的終點
* 終點的位置也是在控件外部
* 我們只需不斷讓ctrX的大小變化即可實現“浪”的效果
*/
mPath.quadTo(ctrX, ctrY, endX, waveY);
// mPath.cubicTo(ctrX, ctrY,
// (vWidth + 1 / 4F * vWidth) / 2, waveY - 1 / 8F * vHeight,
// vWidth + 1 / 4F * vWidth, waveY);
// 圍繞控件閉合曲線
mPath.lineTo(endX, vHeight);
mPath.lineTo(startX, vHeight);
mPath.close();
canvas.drawPath(mPath, mPaint);
/**
* 當控制點的x座標大於或等於終點x座標時更改標識值
*/
if (ctrX >= endX) {
isInc = false;
}
/**
* 當控制點的x座標小於或等於起點x座標時更改標識值
*/
else if (ctrX <= startX) {
isInc = true;
}
// 根據標識值判斷當前的控制點x座標是該加還是減
ctrX = isInc ? ctrX + 20 : ctrX - 20;
if (ctrY <= vHeight) {
ctrY += 2;
waveY += 2;
}
mPath.reset();
invalidate();
}
}