Android貝塞爾曲線的簡單應用之------實現自定義圓形控件內水波紋自動上升效果Demo

先上效果:

在這裏插入圖片描述

gif可能看不到,上兩張截圖

在這裏插入圖片描述在這裏插入圖片描述

貝塞爾曲線知識的簡單應用,自定義了個圓形控件,空間內水波紋自動上升,通過幾個簡單的seekbar做了個簡單的顏色選擇器。
很早之前就聽過說貝塞爾曲線,只是一直沒時間好好學習一番,最近忙裏偷閒,便想着瞭解一下,網上關於貝塞爾曲線的解釋很多,這裏我就暫時不班門弄斧了,如果還不甚瞭解又有興趣瞭解的小夥伴,可以去看看這個作者的博客,其中關於貝塞爾曲線的幾篇寫的還挺通俗易懂的。

部分關鍵代碼如下:

1.爲了控件更靈活易於拓展,自定義一些屬性

<?xml version="1.0" encoding="utf-8"?>
<resources>

    <declare-styleable name="BezierView">
        <!--水位上升動畫的執行時間-->
        <attr name="duration1" format="integer"/>
        <!--水波週期移動動畫的執行時間-->
        <attr name="duration2" format="integer"/>
        <!--水波高度-->
        <attr name="waveHeight" format="integer"/>
        <!--水波長度-->
        <attr name="waveWidth" format="integer"/>
        <!--初始點Y座標,即水位初始位置-->
        <attr name="originY" format="integer"/>
        <!--背景圓的顏色-->
        <attr name="cirColor" format="color"/>
        <!--背景圓的輪廓的顏色-->
        <attr name="cirSideColor" format="color"/>
    </declare-styleable>

2.創建自定義view,onDraw中的代碼如下:

protected void onDraw(Canvas canvas) {
    super.onDraw(canvas);
    //畫背景圓
    mCanvas.drawCircle(radius,radius,radius,bgCirPaint);
    //不斷的計算波浪的路徑
    calculatePath();
    //在背景圓上繪製水波
    mCanvas.drawPath(path,paint);
    //將畫好的圓繪製到畫布上
    canvas.drawBitmap(mbitmap,0,0,null);
    //繪製圓的輪廓(邊)
    canvas.drawCircle(radius,radius,radius,cirPaint);
}

3.計算波浪的路徑path,這裏便用到了貝塞爾曲線來繪製水波紋的路徑:

 private void calculatePath() {
    
            //初始點
            
            path.moveTo(-waveWidth + dex, originY - dey);
            
            for (int i = -waveWidth; i < width + waveWidth; i += waveWidth) {
    
                //二階貝塞爾曲線繪製
                path.rQuadTo(waveWidth / 4, -waveHeight, waveWidth / 2, 0);
                path.rQuadTo(waveWidth / 4, waveHeight, waveWidth / 2, 0);
            }
    
            //繪製連線
            path.lineTo(width, height);
            path.lineTo(0, height);
            path.close();//關閉當前輪廓。如果當前點不等於輪廓的第一個點,則自動添加線段,使其形成閉區間。
        }

4.動畫效果部分:水波上升和水波移動效果,都可以通過屬性動畫來實現,而且實現方式幾乎一樣,這裏是在自定義view內實現一個public的開啓動畫的方法供activity在適當地時候去調用:

public void startAnimation() {

        //初始化水波效果動畫
        animator1 = ValueAnimator.ofFloat(0, 1);//定義一個值從0到1的控制值
        animator1.setDuration(duration2);//水波移動週期時長
        animator1.setRepeatCount(ValueAnimator.INFINITE);//設置循環次數,0爲1次,無窮盡的一直執行:ValueAnimator.INFINITE
        animator1.setInterpolator(new LinearInterpolator());//插值器,線性勻速播放動畫,不設置其實也是默認勻速
        //監聽
        animator1.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator valueAnimator) {
                //獲取屬性動畫當前值(0-1)
                float fraction = (float) animator1.getAnimatedValue();
                dex = (int) (waveWidth * fraction);//根據動畫進行進度,動態修改整條波浪線的長度
                //清空畫布
                if (path != null)
                    path.reset();
                //刷新
                postInvalidate();
            }
        });
        //啓動動畫
        animator1.start();

        //初始化水位上升動畫
        animator2 = ValueAnimator.ofFloat(0, 1);//定義一個值從0到1的控制值
        animator2.setDuration(duration1);//水波上升週期時長
        animator2.setRepeatCount(0);//設置循環次數,0爲1次,無窮盡的一直執行:ValueAnimator.INFINITE
        animator2.setInterpolator(new LinearInterpolator());//插值器,線性勻速播放動畫,不設置其實也是默認勻速
        //監聽
        animator2.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator valueAnimator) {
                //獲取屬性動畫當前值(0-1)
                float fraction = (float) animator2.getAnimatedValue();
                dey = (int) ((height+waveHeight*2) * fraction);//根據動畫進度,dey的值會從0慢慢接近於heitht+waveHeight*2的高度
                //清空畫布
                if (path != null)
                    path.reset();//TODO 作者原文少了這一步
                //刷新
                postInvalidate();
            }
        });
        //啓動動畫
        animator2.start();
    }

關鍵代碼就是上面的這些啦,估計有經驗的小夥伴看到這裏已經知道怎麼做了,要是懶得自己寫,可以直接去下我的demo也行:

Demo下載地址:https://download.csdn.net/download/qq_37717853/10916906

項目參考博客:
1.https://www.cnblogs.com/wjtaigwh/p/6750184.html
2.https://blog.csdn.net/u013087553/article/details/68490170

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章