自定義控制元件一直是讓很多人包括我頭疼的地方,難度較高 且學習資料零碎 直到我發現扔物線大神的HenCoder進階手冊.
這篇文章記錄一下學習過程,以及途中經過精簡的內容.便於日後查閱
1.1 繪製基礎
關鍵詞語: onDraw()方法 Canvas 畫布 Paint畫筆
一切的開始:
繪製圓形:
Paint paint = new Paint();
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
// 繪製一個圓
canvas.drawCircle(300, 300, 200, paint);
}
複製程式碼
- 1.Canvas 類下的所有 draw- 打頭的方法,例如 drawCircle() drawBitmap()。
- 2.Paint 類的幾個最常用的方法。具體是:
Paint.setStyle(Style style) 設定繪製模式
Paint.setColor(int color) 設定顏色
Paint.setStrokeWidth(float width) 設定線條寬度
Paint.setTextSize(float textSize) 設定文字大小
Paint.setAntiAlias(boolean aa) 設定抗鋸齒開關
Canvas.drawColor(@ColorInt int color) 顏色填充.這是最基本的 drawXXX() 方法:在整個繪製區域統一塗上指定的顏色(可以這麼理解: 畫布整個染上了某種顏色), 這類顏色填充方法一般用於在繪製之前設定底色,或者在繪製之後為介面設定半透明蒙版。
類似方法(作用一致) : drawRGB(int r, int g, int b) 和 drawARGB(int a, int r, int g, int b)
drawCircle(float centerX, float centerY, float radius, Paint paint) 畫圓,引數:圓心xy座標 半徑 畫筆.原點是View 左上角的那個點;水平方向是 x 軸,右正左負
例:canvas.drawCircle(300, 300, 200, paint) 如下圖:
劃重點 : 一些獨有資訊(就是隻有它有,別人沒有的資訊.例如畫圓:圓心 半徑) 都會直接作為引數寫進 drawXXX() 方法裡的(比如 drawCircle(centerX, centerY, radius, paint) 的前三個引數)。 而除此之外,其他的都是公有資訊。比如圖形的顏色、空心實心這些,你不管是畫圓還是畫方都有可能用到的,這些資訊則是統一放在 paint 引數裡的
-
drawRect(float left, float top, float right, float bottom, Paint paint) 畫矩形
-
drawPoint(float x, float y, Paint paint) 畫點
-
drawPoints(float[] pts, int offset, int count, Paint paint) / drawPoints(float[] pts, Paint paint) 畫點(批量)
-
drawOval(float left, float top, float right, float bottom, Paint paint) 畫橢圓
-
drawLine(float startX, float startY, float stopX, float stopY, Paint paint) 畫線
-
drawLines(float[] pts, int offset, int count, Paint paint) / drawLines(float[] pts, Paint paint) 畫線(批量)
-
drawRoundRect(float left, float top, float right, float bottom, float rx, float ry, Paint paint) 畫圓角矩形
-
drawArc(float left, float top, float right, float bottom, float startAngle, float sweepAngle, boolean useCenter, Paint paint) 繪製弧形或扇形
-
drawPath(Path path, Paint paint) 畫自定義圖形
Path 方法第一類:直接描述路徑。
* 第一組 : addXxx() ——新增子圖形 eg:addCircle(float x, float y, float radius, Direction dir) 新增圓 還可以新增橢圓 矩形 圓角矩形 * 第二組 : xxxTo() ——畫線(直線或曲線) eg:lineTo(float x, float y) / rLineTo(float x, float y)字首 r 代表 relatively 「相對地」 畫直線. quadTo(float x1, float y1, float x2, float y2) / rQuadTo(float dx1, float dy1, float dx2, float dy2) 畫二次貝塞爾曲線. moveTo(float x, float y) / rMoveTo(float x, float y) 移動到目標位置 兩個特殊的方法: arcTo() 和 addArc()。它們也是用來畫線的,但並不使用當前位置作為弧線的起點。 特殊1:arcTo(RectF oval, float startAngle, float sweepAngle, boolean forceMoveTo) / arcTo(float left, float top, float right, float bottom, float startAngle, float sweepAngle, boolean forceMoveTo) / arcTo(RectF oval, float startAngle, float sweepAngle) 畫弧形 特殊2:addArc(float left, float top, float right, float bottom, float startAngle, float sweepAngle) / addArc(RectF oval, float startAngle, float sweepAngle) close() 封閉當前子圖形它的作用是把當前的子圖形封閉,即由當前位置向當前子圖形的起點繪製一條直線。 複製程式碼
Path 方法第二類:輔助的設定或計算(場景比較少,只講其中一個方法: setFillType(FillType fillType)。)
Path.setFillType(Path.FillType ft) 設定填充方式 FillType 的取值有四個: EVEN_ODD(原理:奇偶原則) WINDING (非零環繞數原則)(預設值) INVERSE_EVEN_ODD INVERSE_WINDING 複製程式碼
-
drawBitmap(Bitmap bitmap, float left, float top, Paint paint) 畫 Bitmap
-
drawText(String text, float x, float y, Paint paint) 繪製文字(Paint.setTextSize(float textSize)設定文字大小)
總結:1.1繪製基礎: Canvas 的 drawXXX() 系列方法和 Paint 的基本使用,就到這裡
想看1.1詳細原文請戳這裡,裡面還有練習專案...
1.2 Paint詳解
emm....這期的內容,只要做到「知道有這麼個東西」,在需要用到的時候能想起來這個功能能不能做、大致用什麼做就好,至於具體的實現,到時候拐回來再翻一次就行了。
複製程式碼
Paint 的 API 大致可以分為 4 類:
1.顏色
1.1 基本顏色
* 直接設定顏色 : setColor(int color) setARGB(int a, int r, int g, int b)
* 設定著色器 : setShader(Shader shader)
> LinearGradient 線性漸變
Shader shader = new LinearGradient(100, 100, 500, 500, Color.parseColor("#E91E63"),Color.parseColor("#2196F3"),Shader.TileMode.CLAMP);
> RadialGradient 輻射漸變(從中心向周圍)
Shader shader = new RadialGradient(300, 300, 200, Color.parseColor("#E91E63"), Color.parseColor("#2196F3"), Shader.TileMode.CLAMP);
> SweepGradient 掃描漸變
Shader shader = new SweepGradient(300, 300, Color.parseColor("#E91E63"),Color.parseColor("#2196F3"));
> BitmapShader 用 Bitmap 的畫素來作為圖形或文字的填充
Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.batman);
Shader shader = new BitmapShader(bitmap, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP);
> ComposeShader 混合著色器
// 第一個 Shader:頭像的 Bitmap
Bitmap bitmap1 = BitmapFactory.decodeResource(getResources(), R.drawable.batman);
Shader shader1 = new BitmapShader(bitmap1, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP);
// 第二個 Shader:從上到下的線性漸變(由透明到黑色)
Bitmap bitmap2 = BitmapFactory.decodeResource(getResources(), R.drawable.batman_logo);
Shader shader2 = new BitmapShader(bitmap2, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP);
// ComposeShader:結合兩個 Shader
Shader shader = new ComposeShader(shader1, shader2, PorterDuff.Mode.SRC_OVER);
1.2 設定顏色過濾器 setColorFilter(ColorFilter colorFilter)
> LightingColorFilter 模擬光照效果
ColorFilter lightingColorFilter = new LightingColorFilter(0x00ffff, 0x000000);
> PorterDuffColorFilter 使用一個指定的顏色和一種指定的 PorterDuff.Mode 來與繪製物件進行合成
PorterDuffColorFilter(int color, PorterDuff.Mode mode)
> ColorMatrixColorFilter 使用一個 ColorMatrix 來對顏色進行處理。 ColorMatrix 這個類,內部是一個 4x5 的矩陣(厲害了)
1.3 setXfermode(Xfermode xfermode) 以繪製的內容作為源影象,以 View 中已有的內容作為目標影象,選取一個 PorterDuff.Mode 作為繪製內容的顏色處理方案
複製程式碼
2.效果
2.1 setAntiAlias (boolean aa) 設定抗鋸齒
2.2 setStyle(Paint.Style style) 設定填充模式
2.3 線條形狀,四個方法:
> setStrokeWidth(float width)設定線條寬度。單位為畫素,預設值是 0。
> setStrokeCap(Paint.Cap cap)設定線頭的形狀。線頭形狀有三種:BUTT 平頭、ROUND 圓頭、SQUARE 方頭。預設為 BUTT。
> setStrokeJoin(Paint.Join join)設定拐角的形狀。有三個值可以選擇:MITER 尖角、 BEVEL 平角和 ROUND 圓角。預設為 MITER。
> setStrokeMiter(float miter)這個方法是對於 setStrokeJoin() 的一個補充,它用於設定 MITER 型拐角的延長線的最大值。
2.4 色彩優化.Paint 的色彩優化有兩個方法: setDither(boolean dither) 和 setFilterBitmap(boolean filter)
> setDither(boolean dither)設定影象的抖動。
> setFilterBitmap(boolean filter)設定是否使用雙線性過濾來繪製 Bitmap 。
2.5 setPathEffect(PathEffect effect)使用 PathEffect 來給圖形的輪廓設定效果。
2.6 setShadowLayer(float radius, float dx, float dy, int shadowColor)在之後的繪製內容下面加一層陰影。
2.7 setMaskFilter(MaskFilter maskfilter)為之後的繪製設定 MaskFilter。 有BlurMaskFilter模糊效果 EmbossMaskFilter浮雕效果
2.8 獲取繪製的 Path.根據 paint 的設定,計算出繪製 Path 或文字時的實際 Path。
> getFillPath(Path src, Path dst) 獲取實際path
> getTextPath(String text, int start, int end, float x, float y, Path path) / getTextPath(char[] text, int index, int count, float x, float y, Path path)獲取文字path
複製程式碼
3.drawText() 相關
方法太多,下一節裡單獨講;
複製程式碼
4.初始化
它們是用來初始化 Paint 物件,或者是批量設定 Paint 的多個屬性的方法
4.1 reset() 重置 Paint 的所有屬性為預設值。相當於重新 new 一個,不過效能當然高一些啦。
4.2 set(Paint src) 把 src 的所有屬性全部複製過來。相當於呼叫 src 所有的 get 方法,然後呼叫這個 Paint 的對應的 set 方法來設定它們。
4.3 setFlags(int flags) 批量設定 flags。相當於依次呼叫它們的 set 方法。例如:
複製程式碼