1. 程式人生 > >自定義View (四): onDraw 之 Canvas畫布

自定義View (四): onDraw 之 Canvas畫布

前面我們瞭解了自定義View的onDraw之paint方法,接下來我們看一下一個比較重要的方法Canvas。
一:認識下Canvas。
Canvas類簡單理解就標示一塊畫布,用paint(畫筆)在上面畫我們想畫的東西,Canvas的方法有很多,可以繪製很多物件,比如:
1.弧線(arcs)
2.填充顏色(grab和color)
3.Bitmap
4.圓(circle和oval)
5.點(point)
6.線(line)
7.矩形(Rect)
8.圖片(Picture)
9.圓角矩形 (RoundRect)
10.文字(text)
11.頂點(Vertices)
12.路徑(path)
canvas.save():把當前的繪製的影象儲存起來,讓後續的操作相當於是在一個新的圖層上的操作。
canvas.restore(); 把當前畫布返回(調整)到上一個save()狀態之前
canvas.translate(dx, dy); //把當前畫布的原點移到(dx,dy),後面的操作都以(dx,dy)作為參照點,預設原點為(0,0)
canvas.scale(x,y);擴大。x為水平方向的放大倍數,y為豎直方向的放大倍數
canvas.rotate(angel):旋轉.angle指旋轉的角度,順時針旋轉。
canvas.transform():切變。所謂切變,其實就是把影象的頂部或底部推到一邊。

canvas.saveLayer(bounds, paint, saveFlags);

二:Canvas的簡單使用
有了上面對Canvas 方法的認識,那麼下面我就用上面的方法來進行相關練習:
1.drawARGB(int a, int r, int g, int b)和drawColor(int color)
不用畫筆,直接填充畫板顏色

@Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        drawNomal(canvas);
//        drawTest(canvas);

    }
    /**
     * 常規繪製  以(0,0)作為座標原點參考點
     * @param canvas
     */
    private void drawNomal(Canvas canvas){
        // 繪製畫布背景
        canvas.drawColor(Color.GRAY);
}

2.drawLine(float startX, float startY, float stopX, float stopY, Paint paint)
畫線。
引數一:線的起始點的X座標
引數二:線的起始點的Y座標
引數三:線的結束點的X座標
引數四:顯得結束點的Y座標
引數五:不說了

canvas.drawLine(50, 50, 450, 50, mPaint);

3.drawArc(RectF oval, float startAngle, float sweepAngle, boolean useCenter, Paint paint)
畫圓弧(順時針):
第一個引數—固定一塊矩形區域作為畫圓弧的範圍。以矩形中心作為圓心畫弧線
第二個引數—起始弧角度
第三個引數—畫過的角度 , 從起始角度順時針轉過的角度畫弧
第四個引數—是否畫出半徑區域,true畫出來的是一個區域塊,false畫出來的是一個弧線。
第五個引數—畫筆

       mPaint.setStyle(Paint.Style.FILL);
        mPaint.setColor(Color.RED);
        //RectF(float left, float top, float right, float bottom)
//        RectF re1 = new RectF(0,300,800,500);
//        canvas.drawArc(re1, 0, 50, false, mPaint);

        RectF re2 = new RectF(0,300,800,500);
        canvas.drawArc(re2, 0, 50, true, mPaint);

RectF 類中四個引數:
第一個引數:矩形區域左邊距離view左側的距離
第二個引數:矩形區域上邊距離view左側的距離
第三個引數:矩形區域右邊距離view頂部的距離, 第三減去第一即是矩形寬度
第四個引數:矩形區域下邊距離view頂部的距離,第四減去第二即是矩形高度
RectF rectF = new RectF(左,上,右,下);

4.drawCircle(float cx, float cy, float radius, Paint paint)
畫圓,至於畫的是實心圓還是圓圈,跟paint的Style屬性有關。
引數一:圓心X座標
引數二:圓心Y座標
引數三:圓半徑
引數四:這還用說麼??!

    mPaint =new Paint();
        // 繪製畫布背景
        canvas.drawColor(Color.WHITE);
        //設定畫筆顏色
        mPaint.setColor(Color.RED);
        //設定畫筆為空心 ,實心
        mPaint.setStyle(Paint.Style.FILL);
      // 畫圓
        canvas.drawCircle(100, 500, 50, mPaint);


5.drawOval(RectF oval, Paint paint)
繪製一個區域的內切圓或內切橢圓(視所定義的矩形而定):

 RectF oval = new RectF(350, 500, 450, 700);
        // 畫橢圓
        canvas.drawOval(oval, mPaint);

6.drawPath(Path path, Paint paint)

繪製路徑。
引數一:
此類很簡單,但是有幾個注意點:
1.path的起始點的設定呼叫方法是 moveTo();如果沒有呼叫此方法,則預設起始點為(0,0)
2.如果要連線起始點和終點,只需要呼叫path.closed();即可
3.連線兩個點,使用path.lineTo();
引數二:畫筆

  //設定Path路徑
        mPaint.setStyle(Paint.Style.STROKE);
        mPaint.setColor(Color.GREEN);
        mPaint.setStrokeWidth(3);
        Path path = new Path();
        path.moveTo(200, 100);
        path.lineTo(620, 80);
        path.lineTo(420, 200);
        path.lineTo(300, 400);
        path.close();
        canvas.drawPath(path, mPaint);

7.drawTextOnPath(@NonNull String text, @NonNull Path path, float hOffset,float vOffset, @NonNull Paint paint)
該方法可以沿著Path路徑繪製文字,其中text指文字內容,hOffset引數指定水平偏移、vOffset指定垂直偏移

        //設定Path路徑
        mPaint.setStyle(Paint.Style.STROKE);
        mPaint.setColor(Color.GREEN);
        mPaint.setStrokeWidth(3);
        Path path = new Path();
        path.moveTo(200, 100);
        path.lineTo(620, 80);
        path.lineTo(420, 200);
        path.lineTo(300, 400);
        path.close();
        mPaint.setTextSize(46);
        canvas.drawPath(path, mPaint);
        //drawTextOnPath(@NonNull String text, @NonNull Path path, float hOffset,float vOffset, @NonNull Paint paint)
        //該方法可以沿著Path路徑繪製文字,其中text指文字內容,hOffset引數指定水平偏移、vOffset指定垂直偏移
        canvas.drawTextOnPath("7qiuwoeruowoqjifasdkfjksjfiojio23ur8950", path, -10, -10, mPaint);

8.drawPoint(float x, float y, Paint paint)
畫點。
需要注意的是,需要設定將畫筆設定下 paint.setStrokeWidth(xxx);
當然也可以給點加點特效: paint.setStrokeCap(Paint.Cap.ROUND);//或者paint.setStrokeCap(Paint.Cap.BUTT);
設定畫筆的樣式,來指定所畫的點的樣式,圓形還是方形

9. drawText(String text, float x, float y, Paint paint)

按照指定座標 繪製文字。float x和 float y表示 其實點的xy座標

drawText(char[] text, int index, int count, float x, float y, Paint paint)
canvas.drawText("零一二三四五六七八九十".toCharArray(),1,3,10,100,paint); 》》》 一二三

drawText(CharSequence text, int start, int end, float x, float y, Paint paint)
canvas.drawText("零一二三四五六七八九十",1,3,10,100,paint); 》》》 一二   含頭不含尾

10.drawPicture(Picture picture, RectF dst) 和 drawBitmap(Bitmap bitmap, float left, float top, Paint paint)  (本部分借鑑)
區別 : drawPicture(向量圖) 和 drawBitmap(點陣圖)
參照:http://blog.csdn.net/u014005316/article/details/54891400

在繪製圖形的過程中,會需要對畫布進行旋轉,縮放,平移等操作,但對畫布進行比如平移操作之後,會對以後畫上去的內容也產生影響,有時,我們只希望這種平移或是旋轉操作只是臨時作用於畫布上的某些內容,這個時候就可以使用save和restore方法,save和restore方法一般是配對使用.
例如:

       canvas.drawText("00000000", 0, 20, paint);
        canvas.translate(200, 200);//將畫布從(0,0)移動一段距離到(200,200)
        canvas.drawText("——2223233———", 0, 20, paint);

    canvas.drawText("00000000", 0, 20, paint);
        canvas.save();
        canvas.translate(200, 200);
        canvas.restore();
        canvas.drawText("——2223233———", 0, 20, paint);
    }


save()在畫布移動前呼叫和restore()方法在畫布移動之後呼叫,這樣 畫布中的內容才不會跟隨畫布移動。

11。位置轉換方法,canvas.rorate和canvas.translate: 這個是我找的,個人比較感興趣奮鬥

    @Override
    protected void onDraw(Canvas canvas) {
        Paint paint = new Paint();
        canvas.drawColor(Color.BLACK);
        paint.setColor(Color.YELLOW);
        paint.setStrokeJoin(Paint.Join.ROUND);
        paint.setStrokeCap(Paint.Cap.ROUND);
        paint.setStrokeWidth(3);
        paint.setAntiAlias(true);
        paint.setStyle(Paint.Style.STROKE);
        canvas.translate(500, 500); //將位置移動畫紙的座標點:150,150// 原點座標 (500,500)
        canvas.drawCircle(0, 0, 200, paint); //畫圓圈(半徑200)  大圓

        //使用path繪製路徑文字
        canvas.save();
        canvas.translate(-100, -165);
        Path path = new Path();
        // TODO: 2017/6/6  
        path.addArc(new RectF(0,0,220,130), -210, 240);
        Paint citePaint = new Paint(paint);
        citePaint.setTextSize(40);
        citePaint.setStrokeWidth(1);
//drawTextOnPath(@NonNull String text, @NonNull Path path, float hOffset,float vOffset, @NonNull Paint paint)
//該方法可以沿著Path路徑繪製文字,其中text指文字內容,hOffset引數指定水平偏移、vOffset指定垂直偏移
        canvas.drawTextOnPath("我愛學習Android", path, 28, 3, citePaint);
        canvas.restore();

        //刻度和數字
        Paint tmpPaint = new Paint(paint); //小刻度畫筆物件
        tmpPaint.setTextSize(25);//1234 數字大小
        tmpPaint.setStrokeWidth(1);

        float  y=200;//刻度圓半徑
        int count = 60; //總刻度數

        for(int i=0 ; i <count ; i++){
            if(i%5 == 0){
                canvas.drawLine(0f, y, 0, y+18f, paint);//大刻度
                canvas.drawText(String.valueOf(i/5+1), -10f, y+44f, tmpPaint);//123456789 10 11 12

            }else{
                canvas.drawLine(0f, y, 0f, y +12f, tmpPaint);//小刻度
            }
            canvas.rotate(360/count,0f,0f); //旋轉畫紙
        }

        //繪製指標
        tmpPaint.setColor(Color.GRAY);
        tmpPaint.setStrokeWidth(4);
        canvas.drawCircle(0, 0, 10, tmpPaint);
        tmpPaint.setStyle(Paint.Style.FILL);
        tmpPaint.setColor(Color.RED);
        canvas.drawCircle(0, 0, 6, tmpPaint);
        canvas.drawLine(0, 20, 0, -150, paint);

    }