圖形繪制-Paint基本使用


Canvas和Paint的關系

在對UI繪制流程的分析中,可以知道performCanvas()方法最終會調用到View#onDraw()方法,並且會傳遞Canvas,那么Canvas到底有什么用呢?

Canvas在UI繪制中扮演的是會話角色,我們通常情況下都能夠知道使用Canvas去 畫圓型,矩形圖片等,但是最終其真正的繪制並不是在我們的android 層面進行的。

通過源碼分析,Canvas 繼承了BaseCanvas

public class Canvas extends BaseCanvas {}

BaseCanvas中,我們可以發現有大量以nDraw開頭的方法,比如drawCircle

public void drawCircle(float cx, float cy, float radius, @NonNull Paint paint) {
    throwIfHasHwBitmapInSwMode(paint);
    nDrawCircle(mNativeCanvasWrapper, cx, cy, radius, paint.getNativeInstance());
}
private static native void nDrawCircle(long nativeCanvas, float cx, float cy, float radius, long nativePaint);

通過上述代碼塊我們可以知道,Canvas並不是具體的執行者,而是一個傳達着, 在Canvas當中我們會將所有的參數信息設置好,然后交由底層去繪制。

我們通過觀察Canvas中的繪制方法,可以發現每一個繪制方法中都有一個Paint類型的參數,那么Paint的職責到底是什么呢?打開Paint的源碼,可以看到:

/**
* The Paint class holds the style and color information about how to draw
* geometries, text and bitmaps.
*/
public class Paint {}

注釋中描述了Paint 在繪制過程中保存了色彩信息和樣式信息。

Paint基礎

Paint方法主要可以抽象成2大類:

設置和獲取圖像繪制、路徑相關數據

設置畫筆樣式

// 設置畫筆填充樣式
paint.style = Paint.Style.STROKE

Paint.Style.FILL :填充內部
Paint.Style.FILL_AND_STROKE :填充內部和描邊
Paint.Style.STROKE :僅描邊
注意 STROKE、FILL_AND_STROKE與FILL模式相比 外輪廓的位置會擴大。

設置畫筆寬度

// 設置畫筆寬度
paint.strokeWidth = 200.0f

抗鋸齒功能

  • 設置抗鋸齒
// 開啟抗鋸齒
paint.isAntiAlias = true
  • 獲取是否開啟抗鋸齒
val isAntiAlias = paint.isAntiAlias

開啟抗鋸齒功能會消耗較大資源,繪制圖形速度會變慢,但開啟后繪制圖像會平滑一些。

設置線冒樣式

// 設置圓形線冒
paint.strokeCap = Paint.Cap.ROUND

Cap.ROUND(圓形線冒)、 Cap.SQUARE(方形線冒) 、Paint.Cap.BUTT(無線冒)

效果圖:image-20201210094248494

代碼如下:

val paint = Paint()
fun init() {
    // 設置畫筆填充樣式
    paint.style = Paint.Style.STROKE
    // 開啟抗鋸齒
    paint.isAntiAlias = true
    // 設置畫筆顏色
    paint.color = Color.RED
    // 設置畫筆寬度
    paint.strokeWidth = 200.0f
    // 設置圓形線冒
    paint.strokeCap = Paint.Cap.ROUND
}


override fun onDraw(canvas: Canvas) {
    super.onDraw(canvas)
    canvas.drawLine(200f, 300f, 400f, 300f, paint)
}

設置連接處線段

// 設置線段鏈接處的樣式
paint.strokeJoin = Paint.Join.MITER

Join.MITER(結合處為銳角)、Join.Round(結合處為圓弧)、Join.BEVEL(結合處為直線)

效果圖:image-20201210094852252

代碼如下:

// 創建畫筆
private val paint: Paint = Paint()
// 創建矩形區域
private val rect: Rect = Rect()


init {
    // 設置畫筆填充樣式
    paint.style = Paint.Style.STROKE
    // 開啟抗鋸齒
    paint.isAntiAlias = true
    // 設置畫筆顏色
    paint.color = Color.RED
    // 設置畫筆寬度
    paint.strokeWidth = 200.0f
    // 設置線段鏈接處於樣式
    paint.strokeJoin = Paint.Join.ROUND
}


override fun onDraw(canvas: Canvas) {
    super.onDraw(canvas)
    rect.set(200, 300, 400, 400)
    canvas.drawRect(rect, paint)
}

設置畫筆傾斜度

// 設置畫筆傾斜度
paint.strokeMiter = 0.8f

清空畫筆復位

// 畫筆復位
paint.reset()

設置外來畫筆

// 設置一個新的畫筆
paint.set(Paint())

獲取與設置alpha值,顏色和ARGB

// 透明度 0 -100
// r、g、b 0-255
paint.setARGB(80,110,234, 125)


// 設置透明度 0(完全透明) - 100 (不透明)
paint.alpha = 100
// 獲取透明度
val alpha = paint.alpha


// 設置顏色
paint.color = Color.BLUE
// 獲取顏色
val color = paint.color

圖像抖動處理

  • 開啟圖像抖動
// 開啟圖像抖動
paint.isDither = true
  • 獲取圖像抖動是否開啟
// 開啟圖像抖動
val isDither = paint.isDither

會使繪制出來的圖像顏色更加平滑、飽滿和圖像更加清晰

設置繪制路徑效果

// 設置虛線
// intervals: 控制實線和實線之后空白線的寬度(數組長度必須為偶數)
// phase: 將View向”左“偏移phase
paint.pathEffect = DashPathEffect(intervals = floatArrayOf(20f,10f,50f,100f), phase = 15f)

CornerPathEffect ——圓形拐角效果
paint.setPathEffect(new CornerPathEffect(100))
利用半徑R=50的圓來代替原來兩條直線間的夾角
DashPathEffect ——虛線效果 畫同一條線段,偏移值為15
paint.setPathEffect(new DashPathEffect(new float[]{20,10,50,100},15))
intervals[]:表示組成虛線的各個線段的長度;整條虛線就是由intervals[]中這些基本線段循環組成的。比如,我們定義new float[] {20,10}; 那這個虛線段就是由兩段線段組成的,第一個可見的線段長為20,每二個線段不可見,長度為10;
phase:開始繪制的偏移值

設置圖形重疊時的處理方式

paint.xfermode = PorterDuffXfermode(PorterDuff.Mode.MULTIPLY)

通過設置xfermode 可以設置許多不同的效果,如 制作橡皮擦, 具體介紹請看 Paint的高級用法

設置MaskFilter

paint.maskFilter = MaskFilter()

可以用不同的MaskFilter實現濾鏡的效果,如濾化,立體等 。

/**
* Create a blur maskfilter.
*
* @param radius 陰影的半徑
 * @param style  NORMOL -- 整個圖像都被模糊掉
 *               SOLID -- 圖像邊界外產生一層與Paint顏色一致陰影效果,不影響圖像的本身
 *               OUTER -- 圖像邊界外產生一層陰影,並且將圖像變成透明效果
 *               INNER -- 在圖像內部邊沿產生模糊效果
* @return
*/
paint.setMaskFilter(new BlurMaskFilter(50, BlurMaskFilter.Blur.NORMAL));
/**
* Create an emboss maskfilter
*
 * @param direction  指定光源的位置,長度為xxx的數組標量[x,y,z]
 * @param ambient    環境光的因子 (0~1),越接近0,環境光越暗
 * @param specular   鏡面反射系數 越接近0,鏡面反射越強
* @param blurRadius 模糊半徑 值越大,模糊效果越明顯
*/
paint.setMaskFilter(new EmbossMaskFilter(new float[]{1,1,1},0.2f,60,80));

設置顏色過濾器

paint.colorFilter = ColorFilter()

可以在繪制顏色時實現不用顏色的變換效果,可以用來設置圖像的黑白效果。

設置圖像效果

paint.shader = Shader()

使用Shader可以繪制出各種漸變效果。Shader有一些子類,如:LinearGradient。

在圖像下設置陰影層

// radius 為陰影的角度
// dx和dy為陰影在x軸和y軸上的距離
// color為陰影的顏色
paint.setShadowLayer(float radius ,float dx,float dy,int color)

設置獲取文字相關的

獲取字符的行間距

val spacing = paint.fontSpacing

設置和獲取字符的間距

// 獲取字符的間距 api >= 21
val letterSpacing = paint.letterSpacing
// 設置字符的間距 api >= 21
paint.letterSpacing = 20f

是否有下划線和設置下划線

// 獲取是否有下划線
val isUnderlineText = paint.isUnderlineText
// 設置下划線
paint.isUnderlineText = true

獲取與設置是否有文本刪除線

// 設置文本刪除線
paint.isStrikeThruText = true
// 獲取文本刪除線
val isStrikeThruText = paint.isStrikeThruText

獲取與設置文字大小

// 獲取文字大小
val textSize = paint.textSize
// 設置文字大小
paint.textSize = 14f

注意: Paint.setTextSize 單位是pxTextView.setTextSize單位是sp

獲取與設置字體類型

// 設置字體樣式
paint.typeface = Typeface.DEFAULT
val typeface = paint.typeface

默認有四種字體樣式: BOLD(加粗、BOLD_ITALIC(加粗並傾斜)、ITALIC(傾斜)、NORMAL(正常)
也可通過Typeface類來自定義個性化字體。

獲取與設置文字傾斜

// 設置文字傾斜度
paint.textSkewX = -0.25f
val textSkewX = paint.textSkewX

參數沒有具體范圍, 官方推薦值為-0.25,值為負則右傾,為正則左傾,默認值為0。

獲取與設置文本對齊方式

// 設置文本的對齊方式
paint.textAlign = Paint.Align.CENTER
val textAlign = paint.textAlign

取值為 CENTER、LEFT、RIGHT,即文字繪制是左邊對齊、右邊還是局中。

亞像素

// 設置亞像素
paint.isSubpixelText = true

固定的幾個范圍:320480,480800,7201280,10801920等,那么如何在同樣的分辨率的顯示器中增強顯示清晰度呢?
亞像素的概念就油然而生了,亞像素就是把兩個相鄰的兩個像素之間的距離再細分,再插入一些像素,這些通過程序加入的像素就是亞像素。在兩個像素間插入的像素個數是通過程序計算出來的,一般是插入兩個、三個或四個。 所以打開亞像素顯示,是可以在增強文本顯示清晰度的,但由於插入亞像素是通過程序計算而來的,所以會耗費一定的計算機性能。

文本折斷

paint.breakText(String text, boolean measureForwards, float maxWidth, float[] measuredWidth)

如文本閱讀器的翻頁效果,我們需要在翻頁的時候動態折斷或生成一行字符串。

ps: xiaowujiang.cn






免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM