天天看點

android 自定義多邊形,Android:自定義view之Canvas繪制圖形

前面講解了onMeasure,接下來講解onDraw,onDraw主要就是繪制,也就是我們真正關心的部分,使用的是Canvas繪圖。

@Override

protected void onDraw(Canvas canvas) {

super.onDraw(canvas);

}

Canvas簡介

Canvas我們可以稱之為畫布,能夠在上面繪制各種東西,是安卓平台2D圖形繪制的基礎,非常強大。

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比較難以了解和使用,故封裝了一些常用的方法。

PS: Canvas常用方法在上面已經列出,當然還存在一些其他的方法未列出,具體可以參考官方文檔 Canvas

Canvas詳解

本篇内容主要講解如何利用Canvas繪制基本圖形。

建立畫筆:

要想繪制内容,首先需要先建立一個畫筆,如下:

// 1.建立一個畫筆

private Paint mPaint = new Paint();

// 3.在構造函數中初始化

public SloopView(Context context, AttributeSet attrs) {

super(context, attrs);

initPaint();

// 2.初始化畫筆

private void initPaint() {

mPaint.setColor(Color.BLACK); //設定畫筆顔色

mPaint.setStyle(Paint.Style.FILL); //設定畫筆模式為填充

mPaint.setStrokeWidth(10f); //設定畫筆寬度為10px

}

在建立完畫筆之後,就可以在Canvas中繪制各種内容了。

繪制矩形:

确定确定一個矩形最少需要四個資料,就是對角線的兩個點的坐标值,這裡一般采用左上角和右下角的兩個點的坐标。

關于繪制矩形,Canvas提供了三種重載方法,第一種就是提供四個數值(矩形左上角和右下角兩個點的坐标)來确定一個矩形進行繪制。 其餘兩種是先将矩形封裝為Rect或RectF(實際上仍然是用兩個坐标點來确定的矩形),然後傳遞給Canvas繪制,如下:

// 第一種

canvas.drawRect(100,100,800,400,mPaint);

// 第二種

Rect rect = new Rect(100,100,800,400);

canvas.drawRect(rect,mPaint);

// 第三種

RectF rectF = new RectF(100,100,800,400);

canvas.drawRect(rectF,mPaint);

以上三種方法所繪制出來的結果是完全一樣的。

android 自定義多邊形,Android:自定義view之Canvas繪制圖形

為什麼會有Rect和RectF兩種?兩者有什麼差別嗎?

答案是肯定有差別,兩者最大的差別就是精度不同,Rect是int(整形)的,而RectF是float(單精度浮點型)的。除了精度不同,兩種提供的方法也稍微存在差别,想了解更多參見官方文檔 Rect 和 RectF

繪制圓角矩形:

RectF rectF = new RectF(100,100,800,400);

canvas.drawRoundRect(rectF,30,30,mPaint);

android 自定義多邊形,Android:自定義view之Canvas繪制圖形

這裡多出來的兩個參數是橢圓的兩個半徑,繪制出的圓弧是橢圓的圓弧.

android 自定義多邊形,Android:自定義view之Canvas繪制圖形

紅線标注的 rx 與 ry 就是兩個橢圓半徑,也就是相比繪制矩形多出來的那兩個參數。

我們了解到原理後,就可以為所欲為了,通過計算可知我們上次繪制的矩形寬度為700,高度為300,當你讓 rx大于350(寬度的一半), ry大于150(高度的一半) 時奇迹就出現了, 你會發現圓角矩形變成了一個橢圓, 他們畫出來是這樣的 ( 為了友善确認我更改了畫筆顔色, 同時繪制出了矩形和圓角矩形 ):

// 矩形

RectF rectF = new RectF(100,100,800,400);

// 繪制背景矩形

mPaint.setColor(Color.GRAY);

canvas.drawRect(rectF,mPaint);

// 繪制圓角矩形

mPaint.setColor(Color.BLUE);

canvas.drawRoundRect(rectF,700,400,mPaint);

android 自定義多邊形,Android:自定義view之Canvas繪制圖形

其中灰色部分是我們所繪制的矩形(參考用),而裡面的圓角矩形則變成了一個橢圓,實際上在rx為寬度的一半,ry為高度的一半時,剛好是一個橢圓,通過上面我們分析的原理推算一下就能得到,而當rx大于寬度的一半,ry大于高度的一半時,實際上是無法計算出圓弧的,是以drawRoundRect對大于該數值的參數進行了限制(修正),凡是大于一半的參數均按照一半來處理。

繪制橢圓:

相對于繪制圓角矩形,繪制橢圓就簡單的多了,因為他隻需要一個矩形矩形作為參數:

// 第一種

RectF rectF = new RectF(100,100,800,400);

canvas.drawOval(rectF,mPaint);

// 第二種

canvas.drawOval(100,100,800,400,mPaint);

同樣,以上兩種方法效果完全一樣,但一般使用第一種。

android 自定義多邊形,Android:自定義view之Canvas繪制圖形

PS: 如果你傳遞進來的是一個長寬相等的矩形(即正方形),那麼繪制出來的實際上就是一個圓。

繪制圓:

繪制圓形也比較簡單, 如下:

canvas.drawCircle(500,500,400,mPaint); // 繪制一個圓心坐标在(500,500),半徑為400 的圓。

繪制圓形有四個參數,前兩個是圓心坐标,第三個是半徑,最後一個是畫筆。

android 自定義多邊形,Android:自定義view之Canvas繪制圖形

繪制圓弧:

繪制圓弧就比較神奇一點了,為了了解這個比較神奇的東西,我們先看一下它需要的幾個參數:

// 第一種

public void drawArc(@NonNull RectF oval, float startAngle, float sweepAngle,

boolean useCenter, @NonNull Paint paint){}

// 第二種

public void drawArc(float left, float top, float right, float bottom, float startAngle,

float sweepAngle, boolean useCenter, @NonNull Paint paint) {}

從上面可以看出,相比于繪制橢圓,繪制圓弧還多了三個參數:

startAngle // 開始角度

sweepAngle // 掃過角度

useCenter // 是否使用中心

通過字面意思我們基本能猜測出來前兩個參數(startAngle, sweepAngel)的作用,就是确定角度的起始位置和掃過角度, 不過第三個參數是幹嘛的?試一下就知道了,上代碼:

RectF rectF = new RectF(100,100,800,400);

// 繪制背景矩形

mPaint.setColor(Color.GRAY);

canvas.drawRect(rectF,mPaint);

// 繪制圓弧

mPaint.setColor(Color.BLUE);

canvas.drawArc(rectF,0,90,false,mPaint);

//-------------------------------------

RectF rectF2 = new RectF(100,600,800,900);

// 繪制背景矩形

mPaint.setColor(Color.GRAY);

canvas.drawRect(rectF2,mPaint);

// 繪制圓弧

mPaint.setColor(Color.BLUE);

canvas.drawArc(rectF2,0,90,true,mPaint);

上述代碼實際上是繪制了一個起始角度為0度,掃過90度的圓弧,兩者的差別就是是否使用了中心點,結果如下:

android 自定義多邊形,Android:自定義view之Canvas繪制圖形

相比于使用橢圓,我們還是使用正圓比較多的,使用正圓展示一下效果:

RectF rectF = new RectF(100,100,600,600);

// 繪制背景矩形

mPaint.setColor(Color.GRAY);

canvas.drawRect(rectF,mPaint);

// 繪制圓弧

mPaint.setColor(Color.BLUE);

canvas.drawArc(rectF,0,90,false,mPaint);

//-------------------------------------

RectF rectF2 = new RectF(100,700,600,1200);

// 繪制背景矩形

mPaint.setColor(Color.GRAY);

canvas.drawRect(rectF2,mPaint);

// 繪制圓弧

mPaint.setColor(Color.BLUE);

canvas.drawArc(rectF2,0,90,true,mPaint);

android 自定義多邊形,Android:自定義view之Canvas繪制圖形

簡要介紹Paint

看了上面這麼多,相信有有人會有疑問,如果我想繪制一個圓,隻要邊不要裡面的顔色怎麼辦?

很簡單,繪制的基本形狀由Canvas确定,但繪制出來的顔色,具體效果則由Paint确定。

如果你注意到了的話,在一開始我們設定畫筆樣式的時候是這樣的:

mPaint.setStyle(Paint.Style.FILL); //設定畫筆模式為填充

為了展示友善,容易看出效果,之前使用的模式一直為填充模式,實際上畫筆有三種模式,如下:

STROKE //描邊

FILL //填充

FILL_AND_STROKE //描邊加填充

為了區分三者效果我們做如下實驗:

Paint paint = new Paint();

paint.setColor(Color.BLUE);

paint.setStrokeWidth(40); //為了實驗效果明顯,特地設定描邊寬度非常大

// 描邊

paint.setStyle(Paint.Style.STROKE);

canvas.drawCircle(200,200,100,paint);

// 填充

paint.setStyle(Paint.Style.FILL);

canvas.drawCircle(200,500,100,paint);

// 描邊加填充

paint.setStyle(Paint.Style.FILL_AND_STROKE);

canvas.drawCircle(200, 800, 100, paint);

android 自定義多邊形,Android:自定義view之Canvas繪制圖形

關于Paint詳細的可以看下官方介紹Paint