本篇接着上一篇的基礎知識來說,今天要學點能看的見的東西了————繪製基礎。
一、繪製的簡要說明
自定義繪製最主要的點就是重寫繪製方法,當我們定義一個類去繼承自View這個類時,會讓你必須重寫幾個構造方法和onDraw(Canvas canvas)方法,那我們最常用的繪製方法就是這個onDraw方法,參數需要一個Canvas對象,我們繪製的關鍵就是通過Canvas提供的各個api去進行繪製、裁剪以及幾何變換,這些我會慢慢的進行整理。本篇既然是基礎,那麼這裏就只講關於繪製的方法,即是drawXXX()方法。先把必須的東西都一下說完,在詳細介紹,所以在這裏還需要用到一個畫筆類:Paint,這個類提供的一些api可以讓我們設置畫筆的顏色、形狀、陰影等等,通過Canvas和Paint的搭配使用之後,我們就可以繪製出各種豐富多彩的圖形了。
二、常用api的說明
1、顏色填充
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
//給View上色爲粉紅色
canvas.drawColor(getResources().getColor(R.color.pageColor));
}
這裏直接調用drawColor()方法,參數填充顏色即可,效果如下:
2、繪製圓形及環形
先看個簡單的,繪製一個實心圓,這裏我們需要藉助Paint對象了哦,首先實例化一個Paint對象,然後調用canvas.drawCircle(圓心橫座標,圓心縱座標,半徑,畫筆對象)方法,各個參數的含義已經很明確了,其中Paint.Style.FILL是實心模式,Paint.Style.STROKE是線條即空心模式。對了,需要說明的一點是,這裏的座標系和我們平時在數學中學的兩維座標系不同,android中每個View自己有一個座標系,原點是View左上角的那個點,水平方向爲X軸,向右爲正向左爲負,豎直方向爲Y軸,向下爲正向上爲負,盜了大神一張圖,上圖:
除了畫實心圓,我們還可以畫空心圓,畫帶有顏色的實心圓,畫圓環等等,因爲使用也比較簡單我就不詳細說明了,具體來看一下代碼,已經給出了註釋:
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG); //開啓抗鋸齒
//實心圓
canvas.drawCircle(100, 300, 50, paint);
//空心圓
paint.setStyle(Paint.Style.STROKE); //設置空心圓
canvas.drawCircle(250, 300, 50, paint);
//粉紅色實心圓
paint.setStyle(Paint.Style.FILL);
paint.setColor(Color.parseColor("#FF4081"));
canvas.drawCircle(400, 300, 50, paint);
//線寬爲10的空心圓
paint.setStyle(Paint.Style.STROKE);
paint.setStrokeWidth(10); //設置線的寬度
canvas.drawCircle(550, 300, 50, paint);
}
這裏需要說明的有一點Paint.ANTI_ALIAS_FLAG這個屬性是給畫筆添加抗鋸齒效果,以保證圖形邊緣平滑,具體的實現效果爲:
3、繪製矩形
我們可以使用canvas.drawRect(float left,float top,float right,float bottom,Paint paint)方法來繪製矩形,還有兩個重載的方法,可以直接傳Rect和RectF對象,具體代碼如下:
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
Paint paint = new Paint();
//畫矩形
paint.setColor(Color.parseColor("#3F51B5"));
canvas.drawRect(100,100,600,300,paint);
// Rect rect = new Rect(100,100,600,300);
// canvas.drawRect(rect,paint);
// RectF rectF = new RectF(100,100,600,300);
// canvas.drawRect(rectF,paint);
}
具體效果如下圖所示:
4、繪製點
我們使用drawPoint(float x, float y, Paint paint)方法來畫點,參數爲點的座標和畫筆對象,點的形狀可以通過paint.setStrokeCap(cap)方法來進行設置,ROUND爲原點,SQUARE爲方點,它們等同於繪製實現圓和實心矩形。另外drawPoints(float[] pts, Paint paint) 這個方法是畫一組點,具體使用方法如下:
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
//手動關閉硬件加速,因爲Canvas和Paint有一些方法不支持硬件加速
//在這裏不加這句話Paint.Cap.Round不起效果,會是方形的
this.setLayerType(LAYER_TYPE_SOFTWARE,null);
Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
//畫圓點
paint.setStrokeWidth(20); //設置點的大小
paint.setStrokeCap(Paint.Cap.ROUND); //設置點的形狀爲原型
paint.setColor(Color.parseColor("#FF4081"));
canvas.drawPoint(100, 100, paint);
//畫方點
paint.setStrokeWidth(30);
paint.setStrokeCap(Paint.Cap.SQUARE); //設置點的形狀爲方形
canvas.drawPoint(200, 100, paint);
//畫一組點
float[] points = {50,200,100,200,50,280,100,280};
canvas.drawPoints(points,paint);
}
它的效果如圖所示:
5、繪製橢圓
我們可以使用drawOval(float left, float top, float right, float bottom, Paint paint)方法來畫橢圓,它還有一個重載的方法drawOval(RectF rect, Paint paint),參數很好理解了,邊界座標和畫筆對象,具體在代碼中來看它是如何使用的:
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
//畫實心橢圓
paint.setStyle(Paint.Style.FILL);
//這個api必須在版本大於21是才能使用,否則程序會crash
// if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
// canvas.drawOval(100,100,400,300,paint);
// }
RectF rectF = new RectF(100,100,400,300);
canvas.drawOval(rectF,paint);
//畫空心橢圓
paint.setStyle(Paint.Style.STROKE);
// if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
// canvas.drawOval(100,400,400,600,paint);
// }
RectF r = new RectF(100,400,400,600);
canvas.drawOval(r,paint);
}
效果如下圖所示:
6、繪製直線
繪製直線就比較簡單了,使用drawLine(float startX, float startY, float stopX, float stopY, Paint paint)方法畫線,參數就是起始點的座標和畫筆對象。另外我們還可以繪製一組直線,組合出漢字或者其他圖形,使用drawLines(float[] pts, Paint paint) 方法批量操作,下面同樣通過代碼來看它的使用:
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
paint.setStrokeWidth(20);
//畫直線
canvas.drawLine(100,100,600,200,paint);
//批量畫線
float[] points = {200,300,600,300,400,300,400,700,200,700,600,700};
canvas.drawLines(points,paint);
}
效果如下圖所示:
7、繪製圓角矩形
使用drawRoundRect(float left, float top, float right, float bottom, float rx, float ry, Paint paint)方法來畫圓角矩形,參數分別爲外輪廓的座標,圓角的橫向半徑,縱向半徑,畫筆對象,使用起來也是很簡單,直接上代碼:
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
//畫實心圓角矩形
RectF r1 = new RectF(100,50,400,200);
canvas.drawRoundRect(r1,30,30,paint);
//畫空心圓角矩形
paint.setStyle(Paint.Style.STROKE);
RectF r2 = new RectF(100,250,400,400);
canvas.drawRoundRect(r2,30,30,paint);
}
效果圖如下所示:
8、繪製弧形或者扇形
這裏使用drawArc(float left, float top, float right, float bottom, float startAngle, float sweepAngle, boolean useCenter, Paint paint)方法來繪製弧形或扇形,通過查看源碼我們可以發現,它底層是通過一個橢圓來描述弧形的,其中參數left、top、right、bottom是所在的橢圓的邊界座標,startAngle是弧形的起始角度,X軸的正向爲0度的位置,順時針爲正逆時針爲負,sweepAngle是弧形範圍角度,useCenter表示是否連接到圓心,爲true表示連接,就是扇形,爲false表示不連接,就是弧形。具體使用方式見代碼:
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
paint.setStyle(Paint.Style.FILL); // 填充模式
RectF rectF = new RectF(200, 100, 600, 500);
// 繪製扇形
canvas.drawArc(rectF, -110, 100, true, paint);
// 繪製弧形
canvas.drawArc(rectF, 20, 140, false, paint);
paint.setStyle(Paint.Style.STROKE);
// 繪製不封口的弧形,即弧線
canvas.drawArc(rectF, 180, 60, false, paint);
}
效果圖如下所示:
9、繪製自定義圖形
說到畫自定義圖形,我們就會用到drawPath(Path path,Paint paint)這個方法了,它是通過描述路徑的方式來繪製圖形的,參數就是描述圖形路徑的對象和畫筆對象。描述路徑的方法又可分爲兩類:添加子圖形和畫線,即addXxx()和xxxTo()兩類,我這裏結合一個繪製心形的案例來介紹其中的一些方法,首先來看lineTo(float x, float y) / rLineTo(float x, float y) 方法,從當前位置向目標位置一條畫線,x,y是目標點的座標,當前位置就是最後一次調用Path方法的位置,初始值爲(0,0),不同的是前者的參數是絕對座標,後者的參數是相對座標;moveTo(float x, float y) / rMoveTo(float x, float y) 這個方法是移動到目標位置,可以用來指定起始點的座標;arcTo(float left, float top, float right, float bottom, float startAngle, float sweepAngle, boolean forceMoveTo)這個方法用來畫弧形,前面的參數和之前的意思一樣,這裏介紹一下forceMoveTo這個參數的意思,它是表示繪製時是否留下移動的軌跡;addArc(float left, float top, float right, float bottom, float startAngle, float sweepAngle)這個方法也是用來畫弧形的,它和arcTo()的區別就是它直接將forceMoveTo置爲true了;drawText(String text, float x, float y, Paint paint)這個方法是用來繪製文字的,參數是文本,位置座標和畫筆對象。具體的實現代碼如下:
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
paint.setColor(Color.parseColor("#FF4081"));
Path path = new Path(); //初始化Path對象
RectF rectF = new RectF(100,200,300,400);
path.addArc(rectF,-225,225);
RectF r = new RectF(300,200,500,400);
path.arcTo(r,-180,225,false);
path.lineTo(300,542);
canvas.drawPath(path,paint);
}
效果圖如下所示:
關於繪製基礎部分的知識點就介紹這麼多,最後通過兩個小案例直方圖和餅圖進行知識點的鞏固,我已經將完整的代碼上傳到GitHub上面了,歡迎大家批評指正。
直方圖和餅圖的效果圖如下:
項目地址:https://github.com/JArchie/CustomViewDemo
我的這篇文章是基於在扔物線大神的系列課程的學習總結,這裏也推薦給大家:https://juejin.im/user/552f20a7e4b060d72a89d87f,實際上這個小項目就是對這個課後作業的解答,我建議大家如果想學習的都去看看大神的這個系列的文章,寫的真的很詳細,值得一看!