步步學習自定義View:Hencoder 精簡版學習筆記(一)

TheShy_發表於2018-04-08

自定義控制元件一直是讓很多人包括我頭疼的地方,難度較高 且學習資料零碎 直到我發現扔物線大神的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 方法。例如:
複製程式碼

最後再強調一遍:這期的內容沒必要全部背會,只要看懂、理解,記住有這麼個東西就行了。以後在用到的時候,再拐回來翻一翻就行了。

原文及練習傳送門

相關文章