1、Paint類
自定義控件具有很強的靈活性,可以根據你的想法畫出各種各樣的圖案,在Android中如果是自定義控件的話,Paint這個類用的還是較多的,先來看一下這個類的註釋:
/**
* The Paint class holds the style and color information about how to draw
* geometries, text and bitmaps.
*/
使用保存的樣式和顏色信息,繪製幾何圖形,文本和bitmap。
2、Paint方法
mPaint.setColor(Color.RED);// 設置顏色
mPaint.setARGB(255, 255, 255, 0); // 設置 Paint對象顏色,範圍爲0~255
mPaint.setAlpha(200); // 設置alpha不透明度,範圍爲0~255
mPaint.setAntiAlias(true); // 抗鋸齒
mPaint.setStyle(Paint.Style.FILL); //描邊效果
mPaint.setStrokeWidth(4);//描邊寬度
mPaint.setStrokeCap(Paint.Cap.ROUND); //圓角效果
mPaint.setStrokeJoin(Paint.Join.MITER);//拐角風格
mPaint.setShader(new SweepGradient(200, 200, Color.BLUE, Color.RED)); //設置環形渲染器
mPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DARKEN)); //設置圖層混合模式
mPaint.setColorFilter(new LightingColorFilter(0x00ffff, 0x000000)); //設置顏色過濾器
3、線條形狀
3.1 Paint. setAntiAlias
設置抗鋸齒
3.2 Paint.Style
paint.setStyle(Paint.Style.FILL); //填充所有
paint.setStyle(Paint.Style.STROKE); //描邊效果,只畫出線條
paint.setStyle(Paint.Style.FILL_AND_STROKE); //填充內部和描邊
3.3 Paint.cap
paint.setStrokeCap(Paint.Cap.BUTT); //默認效果,如繪製的正方形,就是正方行
paint.setStrokeCap(Paint.Cap.ROUND); //繪製的圖形兩邊會有圓角效果,兩邊的圓角是在SQUARE 的基礎上延申出一部分形成圓角
paint.setStrokeCap(Paint.Cap.SQUARE); //BUTT 的基礎上,兩邊延申出去一部分
3.4 Paint.Join
paint.setStrokeJoin(Paint.Join.MITER);//拐角風格,直角
paint.setStrokeJoin(Paint.Join.BEVEL);//拐角風格,切割
paint.setStrokeJoin(Paint.Join.ROUND);//拐角風格,圓角
3.5 Paint. StrokeMiter
paint.setStrokeMiter(1.7f);
對於 setStrokeJoin() 的一個補充,它用於設置 MITER 型拐角的延長線的最大值。
4、drawBitmap
4.1 Paint.setXfermode
4.2 Paint.setDither
設置圖像的抖動
paint.setDither(true);
4.3 Paint.setFilterBitmap
是否使用雙線性過濾來繪製 Bitmap
圖像在放大繪製的時候,默認使用的是最近鄰插值過濾,這種算法簡單,但會出現馬賽克現象;而如果開啓了雙線性過濾,就可以讓結果圖像顯得更加平滑。
paint.setFilterBitmap(true);
5、drawText
5.1 Paint.Align
paint.setTextAlign(Paint.Align.LEFT); //左對齊,默認
paint.setTextAlign(Paint.Align.CENTER);//居中對齊
paint.setTextAlign(Paint.Align.RIGHT); //右對齊
5.2 Paint.FontMetrics
字體的度量,是指對於指定字號的某種字體,在度量方面的各種屬性,其描述參數包括:
Paint.FontMetrics fontMetrics = mPaint.getFontMetrics();
float top = fontMetrics.top;
float ascent = fontMetrics.ascent;
float descent = fontMetrics.descent;
float bottom = fontMetrics.bottom;
float leading = fontMetrics.leading;
baseline:字符基線
ascent:字符最高點到baseline的推薦距離
top:字符最高點到baseline的最大距離
descent:字符最低點到baseline的推薦距離
bottom:字符最低點到baseline的最大距離
leading:行間距,即前一行的descent與下一行的ascent之間的距離
參考:https://blog.csdn.net/flyeek/article/details/43934945
5.3 Paint.Measure
float[] measuredWidth = new float[16];
Paint.FontMetrics fontMetrics = mPaint.getFontMetrics();
//字符的高度
float textHeight = fontMetrics.descent + Math.abs(fontMetrics.ascent);
//字符串的長度;
float textLength = mPaint.measureText(text);
//measuredWidth每一個字符的長度;textWidths字符數
int textWidths = mPaint.getTextWidths(text, measuredWidth);
//截取的最大距離中字符個數
int breakText = mPaint.breakText(text, true, 50, null);
breakText()這個方法:
/**
* 計算出要截取的字符個數
*
* @param text 測量的字符串
* @param start 測量開始的位置
* @param end 測量結束的位置
* @param measureForwards 測量方向,true從前往後,false從後往前
* @param maxWidth 截取的字符串最大寬度
* @param measuredWidth 截取字符串實際寬度
* @return 需要截取的字符個數
*/
public int breakText(CharSequence text, int start, int end,
boolean measureForwards, float maxWidth,
float[] measuredWidth);
5.4 Paint.setShadowLayer
mPaint.setShadowLayer(10, 10, 10, Color.RED);
canvas.drawText("ANDROID", 0, 100, mPaint);
注意:
在硬件加速開啓的情況下, setShadowLayer() 只支持文字的繪製,文字之外的繪製必須關閉硬件加速才能正常繪製陰影。
如果 shadowColor 是半透明的,陰影的透明度就使用 shadowColor 自己的透明度;而如果 shadowColor 是不透明的,陰影的透明度就使用 paint 的透明度。
6、PathEffect
使用 PathEffect 來給圖形的輪廓設置效果。
Android 中的 6 種 PathEffect:
單一效果: CornerPathEffect、DiscretePathEffect、DashPathEffect、PathDashPathEffect
組合效果:SumPathEffect ComposePathEffect
6.1 CornerPathEffect
把所有拐角變成圓角
PathEffect effect = new CornerPathEffect(60);
mPaint.setPathEffect(effect);
canvas.drawPath(mPath, mPaint);
6.2 DiscretePathEffect
把線條進行隨機的偏離,讓輪廓變得亂七八糟。
DiscretePathEffect 具體的做法是,把繪製改爲使用定長的線段來拼接,並且在拼接的時候對路徑進行隨機偏離。DiscretePathEffect(float segmentLength, float deviation) 的兩個參數中, segmentLength 是用來拼接的每個線段的長度, deviation 是偏離量。這兩個值設置得不一樣,顯示效果也會不一樣。
PathEffect effect = new DiscretePathEffect(20, 10);
mPaint.setPathEffect(effect);
canvas.drawPath(mPath, mPaint);
6.3 DashPathEffect
使用虛線來繪製線條。
它的構造方法 DashPathEffect(float[] intervals, float phase) 中, 第一個參數 intervals 是一個數組,它指定了虛線的格式:數組中元素必須爲偶數(最少是 2 個),按照「畫線長度、空白長度、畫線長度、空白長度」……的順序排列,例如上面代碼中的 20, 5, 10, 5 就表示虛線是按照「畫 20 像素、空 5 像素、畫 10 像素、空 5 像素」的模式來繪製;第二個參數 phase 是虛線的偏移量。
PathEffect effect = new DashPathEffect(new float[]{30,15,60, 15}, 10);
mPaint.setPathEffect(effect);
canvas.drawPath(mPath, mPaint);
6.4 PathDashPathEffect
這個方法比 DashPathEffect 多一個前綴 Path ,所以顧名思義,它是使用一個Path 來繪製「虛線」。
它的構造方法:PathDashPathEffect(Path shape, float advance, float phase, Style style );
PathDashPathE中, shape 參數是用來繪製的 Path ; advance 是兩個相鄰的 shape 段之間的間隔,不過注意,這個間隔是兩個 shape 段的起點的間隔,而不是前一個的終點和後一個的起點的距離; phase 和 DashPathEffect 中一樣,是虛線的偏移;最後一個參數 style,是用來指定拐彎改變的時候 shape 的轉換方式。style 的類型爲 PathDashPathEffect.Style ,是一個 enum ,具體有三個值:
TRANSLATE:位移
ROTATE:旋轉
MORPH:變體
Path shape = new Path();
shape.moveTo(0,20);
shape.lineTo(20,0);
shape.lineTo(40, 20);
PathEffect effect = new PathDashPathEffect(shape,50,40, PathDashPathEffect.Style.TRANSLATE);
mPaint.setPathEffect(effect);
canvas.drawRoundRect(0,0, 400,300, 72,72, mPaint);
6.5 SumPathEffect
這是一個組合效果類的 PathEffect 。它的行爲特別簡單,就是分別按照兩種PathEffect 分別對目標進行繪製。
PathEffect dashPathEffect = new DashPathEffect(new float[]{10, 10}, 10);
PathEffect discretePathEffect = new DiscretePathEffect(40, 20);
PathEffect sumPathEffect = new SumPathEffect(dashPathEffect, discretePathEffect);
mPaint.setPathEffect(sumPathEffect);
canvas.drawPath(mPath, mPaint);
6.6 ComposePathEffect
這也是一個組合效果類的 PathEffect 。不過它是先對目標 Path 使用一個PathEffect,然後再對這個改變後的 Path 使用另一個 PathEffect。
PathEffect dashPathEffect = new DashPathEffect(new float[]{10, 10}, 10);
PathEffect discretePathEffect = new DiscretePathEffect(40, 20);
PathEffect sumPathEffect = new ComposePathEffect(dashPathEffect, discretePathEffect);
mPaint.setPathEffect(sumPathEffect);
canvas.drawPath(mPath, mPaint);
它的構造方法ComposePathEffect(PathEffect outerpe, PathEffect innerpe) 中的兩個PathEffect 參數, innerpe 是先應用的, outerpe 是後應用的。所以上面的代碼就是「先偏離,再變虛線」。而如果把兩個參數調換,就成了「先變虛線,再偏離」。
7、MaskFilter
爲之後的繪製設置 MaskFilter。上一個方法 setShadowLayer() 是設置的在繪製層下方的附加效果;而這個 MaskFilter 和它相反,設置的是在繪製層上方的附加效果。
MaskFilter 有兩種: BlurMaskFilter 和 EmbossMaskFilter。
7.1 BlurMaskFilter
模糊效果
MaskFilter filter = new BlurMaskFilter(50, BlurMaskFilter.Blur.INNER);
mPaint.setMaskFilter(filter);
canvas.drawBitmap(bitmap, 100, 100, mPaint);
它的構造方法 BlurMaskFilter(float radius, BlurMaskFilter.Blur style)中, radius 參數是模糊的範圍, style 是模糊的類型。一共有四種:
NORMAL : 內外都模糊繪製
SOLID : 內部正常繪製,外部模糊
INNER : 內部模糊,外部不繪製
OUTER : 內部不繪製,外部模糊
7.2 EmbossMaskFilter
浮雕效果
EmbossMaskFilter (float[] direction, // 3個浮點值的數組,X、Y、Z方向指定光源
float ambient, // 環境光亮度,取值範圍是0~1
float specular, // 反射等級,值如:8
float blurRadius) // 照明前的模糊量,值如:3
MaskFilter filter = new EmbossMaskFilter(new float[]{-1, 1, -1}, 1f, 8, 3.5f);
mPaint.setMaskFilter(filter);
canvas.drawText("ANDROID", 0, 200, mPaint);
效果不是很明顯…
8.Shader
Shader 這個英文單詞很多人沒有見過,它的中文叫做「着色器」,也是用於設置繪製顏色的。在 Android 的繪製裏使用 Shader ,並不直接用 Shader 這個類,而是用它的幾個子類:
LinearGradient、RadialGradient、SweepGradient、BitmapShader、 ComposeShader
8.1 LinearGradient線性渲染
**
* 1.線性渲染,LinearGradient(float x0, float y0, float x1, float y1, @NonNull @ColorInt int colors[], @Nullable float positions[], @NonNull TileMode tile)
* (x0,y0):漸變起始點座標
* (x1,y1):漸變結束點座標
* colors:漸變數組
* positions:位置數組,position的取值範圍[0,1],作用是指定某個位置的顏色值,如果傳null,漸變就線性變化。
* tile:用於指定控件區域大於指定的漸變區域時,空白區域的顏色填充方法,分爲三種:CLAMP(最後1像素拉伸) REPEAT(重複) MIRROR(鏡影)
*/
//渲染一個x和y的座標點是(200, 100),顏色是從綠色到紅色漸變,在0.6f(60%)的時候開始漸變成紅色,1 最後是藍色 ,繪製區域大於渲染器指定區域的填充是1像素拉伸
Shader lineShader = new LinearGradient(0, 0, 200, 0,
new int[]{Color.RED, Color.GREEN, Color.BLUE},
new float[]{0, 0.6f, 1},
Shader.TileMode.REPEAT);
8.2 RadialGradient環形渲染
/**
* 環形渲染,RadialGradient(float centerX, float centerY, float radius, @ColorInt int colors[], @Nullable float stops[], TileMode tileMode)
* centerX ,centerY:shader的中心座標,開始漸變的座標
* radius:漸變的半徑
* centerColor,edgeColor:中心點漸變顏色,邊界的漸變顏色
* colors:漸變顏色數組
* stoops:漸變位置數組,類似掃描漸變的positions數組,取值[0,1],中心點爲0,半徑到達位置爲1.0f
* tileMode:shader未覆蓋以外的填充模式。
*/
Shader shader = new RadialGradient(200, 200, 130,
new int[]{Color.GREEN, Color.YELLOW, Color.RED},
null, Shader.TileMode.REPEAT);
mPaint.setShader(shader);
8.3 SweepGradient掃描渲染
/**
* 掃描渲染,順時針方向逐漸漸變渲染 SweepGradient(float cx, float cy, @ColorInt int color0,int color1)
* cx,cy 漸變中心座標
* color0,color1:漸變開始結束顏色
* colors,positions:類似LinearGradient,用於多顏色漸變,positions爲null時,根據顏色線性漸變
*/
Shader shader = new SweepGradient(200, 200,
new int[]{Color.RED, Color.GREEN, Color.BLUE},
new float[]{0.5f, 0.3f,1});
8.4 BitmapShader位圖渲染
/**
* 位圖渲染,BitmapShader(@NonNull Bitmap bitmap, @NonNull TileMode tileX, @NonNull TileMode tileY)
* Bitmap:構造shader使用的bitmap
* tileX:X軸方向的TileMode
* tileY:Y軸方向的TileMode
REPEAT, 繪製區域超過渲染區域的部分,重複排版
CLAMP, 繪製區域超過渲染區域的部分,會以最後一個像素拉伸排版
MIRROR, 繪製區域超過渲染區域的部分,鏡像翻轉排版
*/
Shader shader = new BitmapShader(mBitmap, Shader.TileMode.MIRROR, Shader.TileMode.MIRROR);
8.5 ComposeShader組合渲染
Bitmap mBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.flower);
Shader bitmapShader = new BitmapShader(mBitmap, Shader.TileMode.REPEAT, Shader.TileMode.REPEAT);
LinearGradient linearGradient = new LinearGradient(0, 0, 200, 200,
new int[]{Color.RED, Color.GREEN, Color.BLUE},
null,
Shader.TileMode.REPEAT);
Shader shader = new ComposeShader(bitmapShader, linearGradient, PorterDuff.Mode.MULTIPLY);
mPaint.setShader(shader);
9、ColorFilter
ColorFilter 這個類,它的名字已經足夠解釋它的作用:爲繪製設置顏色過濾。顏色過濾的意思,就是爲繪製的內容設置一個統一的過濾策略,然後Canvas.drawXXX() 方法會對每個像素都進行過濾後再繪製出來。
ColorFilter 並不直接使用,而是使用它的子類。它共有三個子類:LightingColorFilter、PorterDuffColorFilter 和 ColorMatrixColorFilter。
9.1 LightingColorFilter 光照效果
/**
* 用來模擬簡單的光照效果 LightingColorFilter(@ColorInt int mul, @ColorInt int add)
* mul:和目標像素相乘,默認0xffffff
* add:和目標像素相加,默認0x000000
* R' = R * mul.R / 0xff + add.R
* G' = G * mul.G / 0xff + add.G
* B' = B * mul.B / 0xff + add.B
*/
ColorFilter filter = new LightingColorFilter(0x00ffff, 0x000000);
如果你想去掉原像素中的紅色,可以把它的 mul 改爲 0x00ffff。綠色加強,可以把它的 add 改爲 0x003000。
9.2 PorterDuffColorFilter 混合濾鏡
/**
* 使用一個指定的顏色和一種指定的 PorterDuff.Mode 來與繪製對象進行合成
* PorterDuffColorFilter(@ColorInt int color, @NonNull PorterDuff.Mode mode)
* color: 指定的顏色
* mode:指定的 Mode
*/
ColorFilter filter = new PorterDuffColorFilter(Color.RED, PorterDuff.Mode.MULTIPLY);
9.3 ColorMatrixColorFilter
/**
* 使用一個 ColorMatrix 來對顏色進行處理。 ColorMatrix 這個類,內部是一個 4x5 的矩陣:
* [ a, b, c, d, e,
* f, g, h, i, j,
* k, l, m, n, o,
* p, q, r, s, t ]
* 對於顏色 [R, G, B, A] ,轉換算法是這樣的:
* R’ = a*R + b*G + c*B + d*A + e;
* G’ = f*R + g*G + h*B + i*A + j;
* B’ = k*R + l*G + m*B + n*A + o;
* A’ = p*R + q*G + r*B + s*A + t;
*/
ColorMatrix colorMatrix = new ColorMatrix();
colorMatrix.setSaturation(0.5f);
//colorMatrix.setRotate(0, 90);
//colorMatrix.setScale(0.5f,0.5f,0.5f,0.5f);
ColorFilter filter = new ColorMatrixColorFilter(colorMatrix)
ColorMatrix 有一些自帶的方法可以做簡單的轉換,setSaturation(float sat) 來設置飽和度。