完全自定義控件-Canvas之繪制基本形狀

nabb4738 8年前發布 | 15K 次閱讀 游戲開發 Android開發 移動開發

一.簡介

Canvas 美[?k?nv?s] 畫布

Canvas繪圖有三個基本要素:Canvas、繪圖坐標系以及Paint。

  • Canvas是畫布,我們通過Canvas的各種drawXXX方法將圖形繪制到Canvas上面,在drawXXX方法中我們需要傳入要繪制的圖形的坐標形狀,還要傳入一個畫筆Paint。
  • drawXXX方法以及傳入其中的坐標決定了要繪制的圖形的形狀,比如drawCircle方法,用來繪制圓形,需要我們傳入圓心的x和y坐標,以及圓的半徑。
  • drawXXX方法中傳入的畫筆Paint決定了繪制的圖形的一些外觀,比如是繪制的圖形的顏色,再比如是繪制圓面還是圓的輪廓線等。
  • Canvas的drawXXX方法中傳入的各種坐標指的都是繪圖坐標系中的坐標。在初始狀況下,繪圖坐標系的坐標原點在View的左上角。
    但繪圖坐標系可以改變,例如translate方法,可以平移坐標系。且坐標系的位移是基于當前位置移動,而不是每次基于屏幕左上角的(0,0)點移動。

二.Canvas的常用操作速查表

操作類型 相關API 備注
繪制顏色 drawColor, drawRGB, drawARGB 使用單一顏色填充整個畫布
繪制基本形狀 drawPoint, drawPoints, drawLine, drawLines, drawRect, drawRoundRect, drawOval, drawCircle, drawArc 依次為 點、線、矩形、圓角矩形、橢圓、圓、圓弧
繪制圖片 drawBitmap, drawPicture 繪制位圖和圖片
繪制文本 drawText, drawPosText, drawTextOnPath 依次為 繪制文字、繪制文字時指定每個文字位置、根據路徑繪制文字
繪制路徑 drawPath 繪制路徑,繪制貝塞爾曲線時也需要用到該函數
頂點操作 drawVertices, drawBitmapMesh 通過對頂點操作可以使圖像形變,drawVertices直接對畫布作用、 drawBitmapMesh只對繪制的Bitmap作用
畫布剪裁 clipPath, clipRect 設置畫布的顯示區域
畫布快照 save, restore, saveLayerXxx, restoreToCount, getSaveCount 依次為 保存當前狀態、 回滾到上一次保存的狀態、 保存圖層狀態、 回滾到指定狀態、 獲取保存次數
畫布變換 translate, scale, rotate, skew 依次為 位移、縮放、 旋轉、錯切
Matrix(矩陣) getMatrix, setMatrix, concat 實際畫布的位移,縮放等操作的都是圖像矩陣Matrix,只不過Matrix比較難以理解和使用,故封裝了一些常用的方法。

三.實戰

繪制顏色 drawARGB:

繪制顏色是填充整個畫布,常用于繪制底色。

  1. 新建CanvasView類繼承View
  2. 重寫onDraw
public class CanvasView extends View {

//在代碼中定義和使用時用到的
public CanvasView(Context context) {
    super(context);
}

//在xml中定義我們的自定義屬性時用到
public CanvasView(Context context, AttributeSet attrs) {
    super(context, attrs);
}

//在View中畫出我們需要的內容
@Override
protected void onDraw(Canvas canvas) {
    canvas.drawARGB(255, 139, 197, 186);
}

}</code></pre>

繪制畫布

繪制點 drawPoint:

  1. 在構造函數中初始化畫筆
  2. 重寫onDraw
public class CanvasView extends View {

private Paint mPaint;

//在代碼中定義和使用時用到的
public CanvasView(Context context) {
    super(context);
    init();
}

//在xml中定義我們的自定義屬性時用到
public CanvasView(Context context, AttributeSet attrs) {
    super(context, attrs);
    init();
}

//在構造函數中初始化畫筆
private void init() {
    mPaint = new Paint();
    mPaint.setColor(Color.BLACK);       //設置畫筆顏色
    mPaint.setStyle(Paint.Style.FILL);  //設置畫筆模式為填充
    mPaint.setStrokeWidth(10f);         //設置畫筆寬度為10px
}

//在View中畫出我們需要的內容
@Override
protected void onDraw(Canvas canvas) {
    canvas.drawPoint(100, 100, mPaint);     //在坐標(100,100)位置繪制一個點
    canvas.drawPoints(new float[]{          //繪制一組點,坐標位置由float數組指定
            200, 200,
            300, 400,
            400, 500
    }, mPaint);
}

}</code></pre>

繪制點

繪制直線 drawLine:

protected void onDraw(Canvas canvas) {
        mPaint.setColor(Color.GREEN);// 設置綠色
        canvas.drawLine(60, 40, 100, 40, mPaint);// 畫線
        canvas.drawLine(110, 40, 190, 80, mPaint);// 斜線
        canvas.drawLines(new float[]{               // 繪制一組線 每四數字(兩個點的坐標)確定一條線
                100,200,200,200,
                100,300,200,300
        },mPaint);
    }

繪制直線

繪制矩形 drawRect:

確定確定一個矩形最少需要四個數據,就是對角線的兩個點的坐標值,這里一般采用左上角和右下角的兩個點的坐標。

protected void onDraw(Canvas canvas) {
        //取得畫布的寬高
        int canvasWidth = canvas.getWidth();
        int canvasHeight = canvas.getHeight();

    //設置畫筆的填充色是藍色
    mPaint.setColor(Color.BLUE);
    int left1 = 10;
    int top1 = 10;
    int right1 = canvasWidth / 3;
    int bottom1 = canvasHeight /3;
    canvas.drawRect(left1, top1, right1, bottom1, mPaint);

    //修改畫筆顏色
    mPaint.setColor(Color.RED);
    int left2 = canvasWidth / 3 * 2;
    int top2 = 10;
    int right2 = canvasWidth - 10;
    int bottom2 = canvasHeight / 3;
    canvas.drawRect(left2, top2, right2, bottom2, mPaint);
}</code></pre> 

  • 簡單畫了下法國國旗

繪制矩形

繪制圓角矩形 drawRoundRect:

protected void onDraw(Canvas canvas) {
        mPaint.setColor(0xff8bc5ba);//A:ff,R:8b,G:c5,B:ba
        RectF rectF = new RectF(10,10,300,150);
        //這里的圓弧是橢圓的圓弧,所以要設置橢圓的兩個半徑
        canvas.drawRoundRect(rectF,10,10,mPaint);
    }

rx,ry

繪制圓角矩形

繪制圓、圓環和橢圓 drawCircle、drawOval:

protected void onDraw(Canvas canvas) {
        mPaint.setColor(0xff8bc5ba);
        mPaint.setAntiAlias(true);  //設置畫筆為抗鋸齒模式,不然畫出來太丑了
        mPaint.setStyle(Paint.Style.FILL);//默認繪圖為填充模式
        int canvasWidth = canvas.getWidth();
        int canvasHeight = canvas.getHeight();
        int halfCanvasWidth = canvasWidth / 2;
        int R = canvasHeight / 9;

    // 繪制一個矩形的內切橢圓
    RectF rectF = new RectF(100, 10, 370, 150);
    canvas.drawOval(rectF, mPaint);

    // 繪制一個圓心坐標在(halfCanvasWidth,250),半徑為R 的圓
    canvas.drawCircle(halfCanvasWidth, 250, R, mPaint);

    //通過繪制兩個圓形成圓環
    //1. 首先繪制大圓
    canvas.drawCircle(halfCanvasWidth, 450, R, mPaint);
    //2. 然后繪制小圓,讓小圓覆蓋大圓,形成圓環效果
    int r = (int) (R * 0.75);
    mPaint.setColor(0xffffffff);//將畫筆設置為白色,畫小圓
    canvas.drawCircle(halfCanvasWidth, 450, r, mPaint);

    //通過畫筆的描邊繪圖模式繪制圓環
    mPaint.setColor(0xff8bc5ba);//設置顏色
    mPaint.setStyle(Paint.Style.STROKE);//繪圖為描邊模式
    float strokeWidth = (float) (R * 0.25); //設置線條寬度
    mPaint.setStrokeWidth(strokeWidth);
    canvas.drawCircle(halfCanvasWidth, 650, R, mPaint);
}</code></pre> 

繪制圓、圓環、橢圓

  • 簡要介紹Paint的模式
    • STROKE 描邊,把邊給填充顏色
    • FILL 填充,填充邊中的內容
    • FILL_AND_STROKE 描邊加填充,就是把上面兩個合起來

繪制圓弧 drawArc:

Canvas中提供了drawArc方法用于繪制弧,這里的弧指兩種:弧面和弧線,弧面即用弧圍成的填充面,弧線即為弧面的輪廓線。

public void drawArc(@NonNull RectF oval, float startAngle, float sweepAngle, boolean useCenter, @NonNull Paint paint){}
  • oval是RecF類型的對象,其定義了橢圓的形狀。
  • startAngle指的是繪制的起始角度,如果傳入的startAngle小于0或者大于等于360,那么用startAngle對360進行取模后作為起始繪制角度。
  • sweepAngle指的是從startAngle開始沿著鐘表的順時針方向旋轉掃過的角度。如果sweepAngle大于等于360,那么會繪制完整的橢圓弧。如果sweepAngle小于0,那么會用sweepAngle對360進行取模后作為掃過的角度。
  • useCenter是個boolean值,如果為true,表示在繪制完弧之后,用橢圓的中心點連接弧上的起點和終點以閉合弧;如果值為false,表示在繪制完弧之后,弧的起點和終點直接連接,不經過橢圓的中心點。

    protected void onDraw(Canvas canvas) {
          int canvasWidth = canvas.getWidth();
          int canvasHeight = canvas.getHeight();
    
          //把畫布分成五份
          float ovalHeight = canvasHeight / 5;
          float left = 10 ;
          float top = 0;
          float right = canvasWidth - left;
          float bottom= ovalHeight;
          RectF rectF = new RectF(left, top, right, bottom);
          mPaint.setAntiAlias(true); //抗鋸齒
          mPaint.setStrokeWidth(5);//設置線寬
          mPaint.setColor(0xff8bc5ba);//設置顏色
          mPaint.setStyle(Paint.Style.FILL);//默認設置畫筆為填充模式
    
          //繪制用drawArc繪制完整的橢圓
          canvas.drawArc(rectF, 0, 360, true, mPaint);
    
          //繪制橢圓的四分之一,起點是0度,到90度
          canvas.translate(0, ovalHeight );  //繪圖坐標系平移操作,x軸移動0,y軸移動五分之一個畫布長度
          canvas.drawArc(rectF, 0, 90, true, mPaint);
    
          //繪制橢圓的四分之一,將useCenter設置為false
          canvas.translate(0, ovalHeight );
          canvas.drawArc(rectF, 0, 90, false, mPaint);
    
          //繪制橢圓的四分之一,只繪制輪廓線
          mPaint.setStyle(Paint.Style.STROKE);//設置畫筆為描邊模式
          canvas.translate(0, ovalHeight );
          canvas.drawArc(rectF, 0, 90, true, mPaint);
    
          //繪制帶有輪廓線的橢圓的四分之一
          //1. 先繪制橢圓的填充部分
          mPaint.setStyle(Paint.Style.FILL);//設置畫筆為填充模式
          canvas.translate(0, ovalHeight );
          canvas.drawArc(rectF, 0, 90, true, mPaint);
          //2. 再繪制橢圓的輪廓線部分
          mPaint.setStyle(Paint.Style.STROKE);//設置畫筆為線條模式
          mPaint.setColor(0xff0000ff);//設置輪廓線條為藍色
          canvas.drawArc(rectF, 0, 90, true, mPaint);
      }

繪制圓弧

自定義餅圖:

學了那么大堆基礎終于可以畫個能用的圖了

自定義餅圖

protected void onDraw(Canvas canvas) {

        RectF rectF = new RectF(100, 100, 400, 400);
        mPaint.setAntiAlias(true); //抗鋸齒
        mPaint.setStrokeWidth(5);//設置線寬
        mPaint.setColor(0xFFCCFF00);//設置顏色
        mPaint.setStyle(Paint.Style.FILL);//默認設置畫筆為填充模式

        canvas.drawArc(rectF, 0, 110, true, mPaint);
        mPaint.setColor(0xff8bc5ba);//設置顏色
        canvas.drawArc(rectF, 110, 50, true, mPaint);
        mPaint.setColor( 0xFF800000);//設置顏色
        canvas.drawArc(rectF, 160, 80, true, mPaint);
        mPaint.setColor(0xFFFF8C69);//設置顏色
        canvas.drawArc(rectF, 240, 120, true, mPaint);
    }

這里是 項目地址

參考

http://blog.csdn.net/iispring/article/details/49770651

https://github.com/GcsSloop/AndroidNote/blob/master/CustomView/Advance/%5B02%5DCanvas_BasicGraphics.md

 

來自:http://www.jianshu.com/p/282958cdbf25

 

 本文由用戶 nabb4738 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!