天天看點

【朝花夕拾】Android自定義View篇之(二)Canvas常用功能

上一篇講View的繪制流程中講到過,最後一步是draw流程,在這個過程中,子view需要重寫onDraw方法來畫出自己的内容。在自定義View繪制自身内容的時候,系統提供了3個非常重要的類來幫助開發者畫各種炫酷的圖形:Canvas、Paint、Path。本篇梳理Canvas相關的基礎知識點,主要用于應對工作中繪制任務,實用而且常見。

前言

       轉在請申明,轉自【https://www.cnblogs.com/andy-songwei/p/10960012.html】,謝謝!

       上一篇講View的繪制流程中講到過,最後一步是draw流程,在這個過程中,子view需要重寫onDraw方法來畫出自己的内容。在自定義View繪制自身内容的時候,系統提供了3個非常重要的類來幫助開發者畫各種炫酷的圖形:Canvas、Paint、Path。本篇主要介紹Canvas相關的内容,Paint和Path在後面會單獨再做介紹。官方文檔中介紹的Canvas相關的API很多,本文主要介紹和梳理一些比較常用的實用功能。

       本文的主要内容如下:

【朝花夕拾】Android自定義View篇之(二)Canvas常用功能

一、一切的開始——onDraw

        如下代碼展示了一個自定義view畫圖形的一個非常簡單的示例。這裡onDraw方法的參數Canvas就是本篇的主角了,中文意思“畫布”,意思就是所有“畫”的内容都是在這張畫布上完成的。

1 Paint paint = new Paint();
2 @Override
3 protected void onDraw(Canvas canvas) {
4 super.onDraw(canvas);
5 // 繪制一個原點坐标(300,300),半徑為200的圓
6 canvas.drawCircle(300, 300, 200, paint);
7 }      

     代碼非常簡單,可見自定義繪制上手非常容易。

二、Canvas基本的draw功能

       Canvas包含了一些畫基本圖案的函數,基本都是以drawXXX的形式給出的。

  1、坐标系

       這裡先簡單介紹一下畫圖中所參照的坐标系,是以目前View位置的左上角為原點(0,0),水準方向向右為X軸正方向,豎直向下為Y軸正方向,這裡的View位置是個相對值,它取決于開發者把它放在哪裡。坐标系大緻如下所示,注意和平時我們數學上坐标系略有差别。

【朝花夕拾】Android自定義View篇之(二)Canvas常用功能

  2、Paint

       在Canvas的這些drawXXX方法中會用到paint類,它是畫筆,會決定繪制出來的圖形的顔色,是填充整個圖形還是僅繪制邊框線條等多個屬性。這些會在以後專門介紹Paint的時候再講,這裡先提醒讀者注意,在筆者截取的效果圖中,咱們這裡先隻關注形狀,關于piant,一律先用預設的填充。

  3、drawColor()顔色填充

    (1)函數原型:drawColor(@color int color)。

    (2)作用:将整個繪制區域填充為指定顔色(可以設定透明度)。

    (3)示例:一般有三種方式來引用顔色值

1  //使用系統提供的顔色
2  canvas.drawColor(Color.BLACK);
3  //使用自定義顔色
4  canvas.drawColor(Color.parseColor("#000000"));
5  //使用color.xml中定義的顔色值
6  canvas.drawColor(getResources().getColor(R.color.black));      

    (4)效果:

【朝花夕拾】Android自定義View篇之(二)Canvas常用功能

    (5)其它設定顔色的方法

          1)drawRGB(int r, int g, int b):根據RGB值來設定顔色

          2)drawARGB(int a, int r, int g, int b):根據透明度和RGB的值來設定顔色。

      上述中的幾種方法,适用于在繪制前設定底色,或者在繪制完成後添加一層半透明蒙闆。

  4、drawCircle畫圓

    (1)函數原型drawCircle(float centerX, float centerY, float radius, Paint paint)。參數依次為:X坐标,Y坐标,半徑,畫筆。

    (2)作用:以原點(centerX,centerY),半徑radius,畫一個圓。

    (3)示例:

1  // 繪制一個原點坐标(300,300),半徑為200的圓
2  canvas.drawCircle(300, 300, 200, paint);      

    (4)效果

【朝花夕拾】Android自定義View篇之(二)Canvas常用功能

  5、drawRect畫矩形

    (1)函數原型:drawRect(float left, float top, float right, float bottom, @NonNull Paint paint) 參數分别為左邊、頂部、右邊、底部四條邊的坐标值。

    (2)根據給定的4條邊框的坐标,來畫矩形。

1 canvas.drawRect(100, 100, 500, 500, paint);      
【朝花夕拾】Android自定義View篇之(二)Canvas常用功能

     (5)其他函數

          1) drawRect(@NonNull Rect r, @NonNull Paint paint)。實際上就是将前面函數定義為一個Rect來作為參數,作用和上面一樣。

          2)示例,效果和上述一樣。

1 canvas.drawRect(new Rect(100,100,500,500),mPaint);      

  6、drawPoint畫點

    (1)函數原型:drawPoint(float x, float y, @NonNull Paint paint)。參數x,y分别為該點的坐标,點的大小和形狀由paint決定。

    (2)功能:在指定x,y坐标處畫點

    (3)示例

1 canvas.drawPoint(50, 50, paint);      

    (4)效果(和畫圓很類似,其實也可以用來畫圓)

【朝花夕拾】Android自定義View篇之(二)Canvas常用功能

    (5)畫多個點

          1)drawPoints(float[] pts, int offset, int count,@NonNull Paint paint)。pts 這個數組是點的坐标,每兩個成一對; offset 表示跳過數組的前幾個數再開始記坐标; count 表示一共有多個數參與繪制。

          2)示例:

1  float[] points = {0, 0, 50, 50, 50, 100, 100, 50, 100, 100, 150, 50};
2  canvas.drawPoints(points, 2 /* 跳過兩個數,即前兩個 0 */,
3  8 /* 一共繪制 8 個數(4 個點)*/, paint);      

          3)效果。效果圖中4個點的坐标分别為(50,50)、(50,100)、(100,50)、(100,100)

【朝花夕拾】Android自定義View篇之(二)Canvas常用功能

          4)drawPoints( @NonNull float[] pts, @NonNull Paint paint);就是預設将上述函數的offset設定為0,count設定為所有資料參與繪制。

  7、drawOval畫橢圓

    (1)函數原型:drawOval(float left, float top, float right, float bottom, @NonNull Paint paint)。參數分别為四個頂點所在切線坐标。

    (2)作用:4個參數确定了一個矩形的4條邊框,這個矩形确定了一個橢圓。該函數用于畫出這個指定的橢圓。

1 canvas.drawOval(50, 50, 350, 200, paint);      
【朝花夕拾】Android自定義View篇之(二)Canvas常用功能

    (5)其它構造函數 : drawOval(RectF rect, Paint paint)

  8、drawLine畫直線

    (1)函數原型:drawLine(float startX, float startY, float stopX, float stopY, Paint paint)。參數值分别為起始點坐标和結束點坐标。

    (2)作用:根據給定的起始點和結束點畫直線

1 canvas.drawLine(200, 200, 800, 500, paint);      
【朝花夕拾】Android自定義View篇之(二)Canvas常用功能

    (5) 批量畫線:drawLines(float[] pts, int offset, int count,Paint paint) / drawLines(float[] pts, Paint paint)。使用方法參照批量畫圓。

  9、drawRoundRect畫圓角矩形

    (1)函數原型:drawRoundRect(float left, float top, float right, float bottom, float rx, float ry, Paint paint)。

    (2)該函數的參數、作用、構造函數等可以參看矩形的繪制。不同點是多了rx和ry,它們表示頂點圓角的X軸方向半徑和Y軸方向半徑。

1 canvas.drawRoundRect(100, 100, 500, 300, 50, 50, paint);      
【朝花夕拾】Android自定義View篇之(二)Canvas常用功能

  10、drawArc畫弧線或扇形

    (1)函數原型:drawArc(float left, float top, float right, float bottom, float startAngle,float sweepAngle, boolean useCenter, @NonNull Paint paint)。扇形或者弧線,都是橢圓(圓可以看成是橢圓的特殊情形)上的一部分,是以畫扇形或者弧線需要先确定好橢圓,前4個參數就是用于确定這個橢圓。startAngle表示起始角度,X軸正方向(即水準向右方向)為0度,順時針為正角度,逆時針為負角度。sweepAngle表示弧線/扇形劃過的角度,依然是順時針為正,逆時針為負;useCenter表示是否連到圓心,true表示連到,表示扇形,false表示不連到,表示弧線。

    (2)示例:

1  canvas.drawArc(200, 100, 800, 500, -110, 100, true, paint); // 繪制扇型
2  canvas.drawArc(200, 100, 800, 500, 20, 140, false, paint); // 繪制弧形      

    (3)效果(paint.setStyle(Paint.Style.STROKE))

【朝花夕拾】Android自定義View篇之(二)Canvas常用功能

  11、drawPath畫自定圖形

    (1)函數原型:drawPath(Path path, Paint paint) 

    (2)根據path定義的形狀來繪制。這個會在後續文章中詳細講。

  12、drawBitmap

    (1)函數原型:drawBitmap(Bitmap bitmap, float left, float top, Paint paint)。參數bitmap表示要繪制的圖檔對象;left,top表示要顯示的bitmap對象的左上角左邊位置。

    (2)作用:把指定的bitmap對象中的像素複制到指定位置。

1 Bitmap bitmap = BitmapFactory.decodeResource(getResources(),R.drawable.test);
2 canvas.drawBitmap(bitmap,100,50,paint);      
【朝花夕拾】Android自定義View篇之(二)Canvas常用功能

    (5)重載方法

          drawBitmap(Bitmap bitmap, Rect src, RectF dst, Paint paint);

          drawBitmap(Bitmap bitmap, Rect src, Rect dst, Paint paint);

          drawBitmap(Bitmap bitmap, Matrix matrix, Paint paint);

       它們可以指定複制原bitmap中的指定區域(Rect src來确定),到畫布中的指定位置(Rect dst)來确定。

  13、drawText繪制文字

        函數原型:drawText(String text, float x, float y, Paint paint)。界面裡所有的顯示内容,都是繪制出來的,包括文字。 drawText() 這個方法就是用來繪制文字的。參數 text 是用來繪制的字元串, x 和 y 是繪制的起點坐标。文字的繪制在後面也會單獨詳細說明。

三、Canvas實作裁剪

       根據給定的範圍,對指定的bitmap進行裁剪,裁剪之後再進行繪制。範圍裁剪有兩個方法:clipRect()和clipPath()。前者會截取一個矩形範圍,而後者path指定的形狀更多,是以裁剪的形狀也會更多。

  1、Canvas.save()和Canvas.restore()

       在裁剪的過程中,要加上這兩句代碼。它們用于儲存和恢複繪制範圍,如果不加容易出現幹擾。

  2、clipRect()

1 canvas.save();
2 //目标bitmap
3 Bitmap bitmap = BitmapFactory.decodeResource(getResources(),R.drawable.test);
4 //确定需要裁剪的矩形範圍
5 canvas.clipRect(left, top, right, bottom);
6 //在指定的x,y坐标開始繪制裁剪後的bitmap
7 canvas.drawBitmap(bitmap, x, y, paint);
8 canvas.restore();      

 裁剪後的效果如下圖所示:

【朝花夕拾】Android自定義View篇之(二)Canvas常用功能

  3、clipPath()

      Canvas.clipRect(Path path) 用法完全一樣,隻是把參數換成了 Path ,是以能裁切的形狀更多一些。其對應有一個方法Canvas.clipOutPaht(Path path),反向裁剪,效果可以從截圖中看出來。

canvas.save();
canvas.clipPath(path1);
canvas.drawBitmap(bitmap, point1.x, point1.y, paint);
canvas.restore();
canvas.save();
canvas.clipOutPath(path);
canvas.drawBitmap(bitmap, point2.x, point2.y, paint);
canvas.restore();      
【朝花夕拾】Android自定義View篇之(二)Canvas常用功能

這個功能對顯示原型頭像比較有幫助。

四、Canvas實作幾何變換

       幾何變換的使用大概分為三類:使用 Canvas 來做常見的二維變換;使用 Matrix 來做常見和不常見的二維變換;使用 Camera 來做三維變換。

  1、使用 Canvas 來做常見的二維變換

    (1)Canvas.translate(float dx, float dy) 平移。參數裡的  dx 和  dy 表示橫向和縱向的位移。

    (2)Canvas.rotate(float degrees, float px, float py) 旋轉

    (3)Canvas.scale(float sx, float sy, float px, float py)放大縮小

    (4)Canvas.skew(float sx, float sy) 錯切,就是傾斜的意思。

1 canvas.save();
 2 //水準向X軸正方向移動200px
 3 canvas.translate(200, 0);
 4 //以給定的點為軸旋轉45度
 5 canvas.rotate(45, centerX, centerY);
 6 //以圖檔中心為軸,水準和豎直方向各放大為原來的1.3倍
 7 canvas.scale(1.3f, 1.3f, x + bitmapWidth / 2, y + bitmapHeight / 2);
 8 canvas.skew(0, 0.5f);
 9 canvas.drawBitmap(bitmap, x, y, paint);
10 canvas.restore();      

  2、使用 Matrix 來做變換

       使用Matrix可以做正常的幾何變換,還可以對圖形進行自定義變換。在做正常的幾何變換時,和前面介紹的用Canvas實作正常變換,功能一樣,選其一即可。

    (1)使用Matrix做正常變換

       使用Matrix 來做正常變換主要分三個步驟(1)建立Matrix對象;(2)Matrix.pre/postTranslate/Rotate/Scale/Skew()設定幾何變換;(3)Canvas.setMatrix(matrix)或Canvas.concat(matrix)把幾何變換應用到Canvas中(盡量用後者)。

1 //1.建立Matrix對象
 2 Matrix matrix = new Matrix();
 3 matrix.reset();
 4 //2.幾何變換
 5 matrix.postTranslate(0,100);
 6 matrix.postRotate(45,bitmap.getWidth()/2,bitmap.getHeight()/2);
 7 matrix.postScale(1.3f,1.3f,x+bitmap.getWidth()/2,y+bitmap.getHeight()/2);        
 8 matrix.postSkew(0,0.5f);
 9 canvas.save();
10 //3.把幾何變換應用到Canvas中
11 canvas.concat(matrix);
12 canvas.drawBitmap(bitmap,x,y,paint1);
13 canvas.restore();      

    (2)使用Matrix做自定義變換

       使用Maxtrix做自定義變換,可以對圖形進行任意拉伸,如下圖所示:

【朝花夕拾】Android自定義View篇之(二)Canvas常用功能

       這需要用到Matrix提供的setPolyToPoly方法來實作,具體的使用這裡不做介紹,請查閱【個人記錄 View Matrix setPolyToPoly】。

  3、使用 Camera 來做三維變換

       這一塊沒有使用過,這裡不做介紹,知道有這個功能即可。

結語

       本文主要就是記錄和梳理學習Canvas中的一些要點,非常基礎,但都實用和常見。内容的來源是騰訊課堂中“仍物線學堂”中課件,特在此聲明。