概念:
畫筆,保存了繪製幾何圖形,文本和位圖的樣式和顏色信息。
常用API:
常用API主要如顏色效果和文本相關等。
當我們調用常用API的時候直接調用native方法。
初始化
mPaint = new Paint(); //初始化
mPaint.setAntiAlias(true); // 抗鋸齒
描邊效果
mPaint.setStyle(Paint.Style.FILL); //描邊效果
setStyle裏面有三種屬性
public enum Style {
FILL (0),
STROKE (1),
FILL_AND_STROKE (2);
...
}
FILL屬性:
STROKE屬性:
FILL_AND_STROKE
兩種同時作用
描邊寬度
mPaint.setStrokeWidth(4);//描邊寬度
上圖中圓環的寬度
圓角效果
mPaint.setStrokeCap(Paint.Cap.ROUND); //圓角效果
Paint.Cap.ROUND裏面有三種屬性
public enum Cap {
BUTT (0),
ROUND (1),
SQUARE (2);
private Cap(int nativeInt) {
this.nativeInt = nativeInt;
}
final int nativeInt;
}
如果是畫直線
mPaint = new Paint(); //初始化
mPaint.setStrokeWidth(44);//描邊寬度
mPaint.setStrokeCap(Paint.Cap.ROUND); //圓角效果
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
canvas.drawLine(400,400,600,400,mPaint);
}
拐角風格
setStrokeJoin(Paint.Join join)
設置線段連接處樣式,取值有:Join.MITER(結合處爲銳角)、Join.Round(結合處爲圓弧)、Join.BEVEL(結合處爲直線)
設置環形渲染器
mPaint.setShader(new SweepGradient(200, 200, Color.BLUE, Color.RED)); //設置環形渲染器
設置圖層混合模式
mPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DARKEN)); //設置圖層混合模式
設置顏色過濾器
mPaint.setColorFilter(new LightingColorFilter(0x00ffff, 0x000000)); //設置顏色過濾器 光照效果
設置雙線性過濾
mPaint.setFilterBitmap(true); //設置雙線性過濾 將圖片過度平滑
設置畫筆遮罩濾鏡 ,傳入度數和樣式
mPaint.setMaskFilter(new BlurMaskFilter(10, BlurMaskFilter.Blur.NORMAL));//設置畫筆遮罩濾鏡 ,傳入度數和樣式
設置文本縮放倍數
mPaint.setTextScaleX(2);// 設置文本縮放倍數
設置字體大小
// mPaint.setTextSize(38);// 設置字體大小
對其方式
// mPaint.setTextAlign(Paint.Align.LEFT);//對其方式
設置下劃線
// mPaint.setUnderlineText(true);// 設置下劃線
文本大小寬度字體度量
// String str = "Android";
// Rect rect = new Rect();
// mPaint.getTextBounds(str, 0, str.length(), rect); //測量文本大小,將文本大小信息存放在rect中
// mPaint.measureText(str); //獲取文本的寬
// mPaint.getFontMetrics(); //獲取字體度量對象
對於指定字號的某種字體,再度量方面的各種屬性。參數包括:
- baseline:字符基線
- ascent:字符最高點到baseline的推薦距離
- top:字符最高點到baseline的最大距離
- descent:字符最低點到baseline的推薦距離
- bottom:字符最低點到baseline的最大距離
- leading:行間距,即前一行的descent與下一行的ascent之間的距離
右鍵圖片另存爲,查看大圖
Paint顏色相關
- setcolor( int color)參數具體的顏色值,16 進制數值,0XFFF000
- . setARGB(inta,intr,intg,intb)參數分別透明度,紅,綠,藍。0-255 數值
- shader( Shadershader)參數着色器對象,一般使用 shader 的幾個子類
- Lineargradient:線性渲染
- RadialGradient:環形渲染
- SweepGradient:掃描渲染
- BitmapShader:位圖渲染
- ComposeShader:組合渲染,例如 LinearGradient+ Bitmap shader
- setColorFilter( Colorfilter colorfilter)設置顏色過濾。一般使用
Colorfilter 三個子類:
- Lighting ColorFilter:光照效果
- PorterDuffcolorfilter:指定一個顏色和一種 PorterDuff Mode 與繪製對象進行合成
- ColorMatrixcolorfilter:使用一個 ColorMatrix 來對顏色進行處理
LinearGradients線性渲染
public LinearGradient (float x0,
float y0,
float x1,
float y1,
long[] colors,
float[] positions,
Shader.TileMode tile)
參數 | |
---|---|
x0 yo x1 y1 | 漸變的兩個端點的位置 |
color0 color1 | 是端點的顏色 |
tile | 端點範圍之外的着色規則,類型是 TileMode |
使用:
/**
* 線性渲染,LinearGradient(float x0, float y0, float x1, float y1, @NonNull @ColorInt int colors[], @Nullable float positions[], @NonNull TileMode tile)
* (x0,y0):漸變起始點座標
* (x1,y1):漸變結束點座標
* color0:漸變開始點顏色,16進制的顏色表示,必須要帶有透明度
* color1:漸變結束顏色
* colors:漸變數組
* positions:位置數組,position的取值範圍[0,1],作用是指定某個位置的顏色值,如果傳null,漸變就線性變化。
* tile:用於指定控件區域大於指定的漸變區域時,空白區域的顏色填充方法
*/
mShader = new LinearGradient(0, 0, 500, 500, new int[]{Color.RED, Color.BLUE, Color.GREEN}, new float[]{0.f,0.7f,1}, Shader.TileMode.REPEAT);
mPaint.setShader(mShader);
canvas.drawCircle(250, 250, 250, mPaint);
效果
注意:
紅到藍漸變
new int[]{Color.RED, Color.BLUE, Color.GREEN}, new float[]{0.f,0.7f,1}
個數是相對應的
color.red和0.f對應
Color.BLUE和0.7f對應
Color.GREEN和1對應
RadialGradient環形渲染
public RadialGradient (float centerX, float centerY, float radius, int centerColor, int edgeColor, Shader.TileMode tileMode)
參數 | |
---|---|
centerX centerY | 輻射中心的座標 |
radius | 輻射半徑 |
centerColor | 輻射中心的顏色 |
tileMode | 輻射範圍之外的着色規則,類型是 TileMode |
使用:
/**
* 環形渲染,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未覆蓋以外的填充模式。
*/
mShader = new RadialGradient(250, 250, 250, new int[]{Color.GREEN, Color.YELLOW, Color.RED}, null, Shader.TileMode.CLAMP);
mPaint.setShader(mShader);
canvas.drawCircle(250, 250, 250, mPaint);
效果
SweepGradient 掃描渲染
public SweepGradient (float cx, float cy, int color0, int color1)
參數 | |
---|---|
cx cy | 掃描的中心 |
color0 | 掃描的起始顏色 |
color1 | 掃描的終止顏色 |
使用:
/**
* 掃描渲染,SweepGradient(float cx, float cy, @ColorInt int color0,int color1)
* cx,cy 漸變中心座標
* color0,color1:漸變開始結束顏色
* colors,positions:類似LinearGradient,用於多顏色漸變,positions爲null時,根據顏色線性漸變
*/
mShader = new SweepGradient(250, 250, Color.RED, Color.GREEN);
mPaint.setShader(mShader);
canvas.drawCircle(250, 250, 250, mPaint);
效果
位圖渲染
public BitmapShader (Bitmap bitmap, Shader.TileMode tileX, Shader.TileMode tileY)
參數 | |
---|---|
bitmap | 用來做模板的 Bitmap對象 |
tileX | 橫向的着色規則 ,類型是TileMode |
tileY | 縱向的着色規則 ,類型是TileMode |
使用:
/**
* 位圖渲染,BitmapShader(@NonNull Bitmap bitmap, @NonNull TileMode tileX, @NonNull TileMode tileY)
* Bitmap:構造shader使用的bitmap
* tileX:X軸方向的TileMode
* tileY:Y軸方向的TileMode
* REPEAT, 繪製區域超過渲染區域的部分,重複排版
* CLAMP, 繪製區域超過渲染區域的部分,會以最後一個像素拉伸排版
* MIRROR, 繪製區域超過渲染區域的部分,鏡像翻轉排版
*/
mShader = new BitmapShader(mBitmap, Shader.TileMode.REPEAT, Shader.TileMode.MIRROR);
mPaint.setShader(mShader);
canvas.drawRect(0,0,500, 500, mPaint);
鏡像是因爲MIRROR
重複是因爲REPEAT
還有一個CLAMP,將圖片最後一個拉伸
如果改成橫軸改成 CLAMP
mShader = new BitmapShader(mBitmap, Shader.TileMode.CLAMP, Shader.TileMode.MIRROR);
mPaint.setShader(mShader);
canvas.drawRect(0,0,500, 500, mPaint);
組合渲染
public ComposeShader (Shader shaderA, Shader shaderB, PorterDuff.Mode mode)
參數 | |
---|---|
shaderA shaderB | 兩個相繼使用的 Shader |
mode | 兩個Sharder的疊加模式,ShaderA 和 shaderB應該怎樣共同繪製。它的類型是PorterDuff.Mode |
/**
* 組合渲染,
* ComposeShader(@NonNull Shader shaderA, @NonNull Shader shaderB, Xfermode mode)
* ComposeShader(@NonNull Shader shaderA, @NonNull Shader shaderB, PorterDuff.Mode mode)
* shaderA,shaderB:要混合的兩種shader
* Xfermode mode: 組合兩種shader顏色的模式
* PorterDuff.Mode mode: 組合兩種shader顏色的模式
*/
BitmapShader bitmapShader = new BitmapShader(mBitmap, Shader.TileMode.REPEAT, Shader.TileMode.REPEAT);
LinearGradient linearGradient = new LinearGradient(0, 0, 1000, 1600, new int[]{Color.RED, Color.GREEN, Color.BLUE}, null, Shader.TileMode.CLAMP);
mShader = new ComposeShader(bitmapShader, linearGradient, PorterDuff.Mode.MULTIPLY);
mPaint.setShader(mShader);
canvas.drawCircle(250, 250, 250, mPaint);
Shader.TileMode着色模式
ShaderTileMode着色模式
Shader.TileMode.CLAMP 超出的部分以最後一個像素來排版
Shader.TileMode.MIRROR 超出的部分以鏡像翻轉來排版
Shader.TileMode.REPEAT 超出的部分重複排版
使用:
mShader = new BitmapShader(mBitmap, Shader.TileMode.REPEAT, Shader.TileMode.MIRROR);
mPaint.setShader(mShader);
canvas.drawRect(0,0,500, 500, mPaint);
PorterDuff.Mode圖層混合模式
它將所繪製圖形的像素與Canvas中對應位置的像素按照一定規則進行混合,形成新的像素值,從而更新 Canvas中最終的像素顏色值
18種模式
public class PorterDuff {
public PorterDuff() {
throw new RuntimeException("Stub!");
}
public static enum Mode {
ADD,
CLEAR,
DARKEN,
DST,
DST_ATOP,
DST_IN,
DST_OUT,
DST_OVER,
LIGHTEN,
MULTIPLY,
OVERLAY,
SCREEN,
SRC,
SRC_ATOP,
SRC_IN,
SRC_OUT,
SRC_OVER,
XOR;
private Mode() {
}
}
}
三個使用的地方
//1.ComposeShader
//2.畫筆Paint.setXfermode()
//3.PorterDuffColorFilter
首先禁止硬件加速
//禁止硬件加速
setLayerType(View.LAYER_TYPE_SOFTWARE, null);
谷歌提供APIDemos教我們如何使用
https://github.com/THEONE10211024/ApiDemos
找到
XfermodesActivity
離屏繪製
通過使用離屏緩衝,把要繪製的內容單獨繪製在緩衝層,保證 Xfermode的使用不會出現錯誤的結果。
使用離屏緩衝有兩種方式
第一種
Canvas saveLayer()可以做短時的離屏緩衝,在繪製之前保存,繪製之後恢復
第二種
View.setLayerType()直接把整個View都繪製在離屏緩衝中。
setLayerType(LAYER_TYPE_ HARDWARE)使用GPU來緩衝,
setLayerType(LAYER_TYPE_SOFTWARE)使用一個 Bitmap來緩衝
先看第一種:
public class XfermodeView extends View {
private Paint mPaint;
private int mWidth, mHeight;
public XfermodeView(Context context) {
this(context, null);
}
public XfermodeView(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public XfermodeView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init();
}
private void init() {
//初始化畫筆
mPaint = new Paint();
mPaint.setColor(Color.RED);
mPaint.setStyle(Paint.Style.FILL_AND_STROKE);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
mWidth = MeasureSpec.getSize(widthMeasureSpec);
mHeight = MeasureSpec.getSize(heightMeasureSpec);
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
//1.ComposeShader
//2.畫筆Paint.setXfermode()
//3.PorterDuffColorFilter
//禁止硬件加速
setLayerType(View.LAYER_TYPE_SOFTWARE, null);
setBackgroundColor(Color.GRAY);
//離屏繪製
int layerId = canvas.saveLayer(0,0, getWidth(), getHeight(), mPaint, Canvas.ALL_SAVE_FLAG);
//目標圖
canvas.drawBitmap(createRectBitmap(mWidth, mHeight), 0, 0, mPaint);
//設置混合模式
mPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_IN));
//源圖,重疊區域右下角部分
canvas.drawBitmap(createCircleBitmap(mWidth, mHeight), 0, 0, mPaint);
//清除混合模式
mPaint.setXfermode(null);
canvas.restoreToCount(layerId);
}
//畫矩形Dst
public Bitmap createRectBitmap(int width, int height) {
Bitmap bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(bitmap);
Paint dstPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
dstPaint.setColor(0xFF66AAFF);
canvas.drawRect(new Rect(width / 20, height / 3, 2 * width / 3, 19 * height / 20), dstPaint);
return bitmap;
}
//畫圓src
public Bitmap createCircleBitmap(int width, int height) {
Bitmap bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(bitmap);
Paint scrPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
scrPaint.setColor(0xFFFFCC44);
canvas.drawCircle(width * 2 / 3, height / 3, height / 4, scrPaint);
return bitmap;
}
}
效果
如果去掉離屏繪製,將如下代碼註釋掉
//離屏繪製
int layerId = canvas.saveLayer(0,0, getWidth(), getHeight(), mPaint, Canvas.ALL_SAVE_FLAG);
canvas.restoreToCount(layerId);
則效果
注意
添加離屏繪製,是先將矩形和圓合成一個圖形,然後繪製到canvas中,再添加背景 setBackgroundColor(Color.GRAY);
而不添加離屏繪製,是將背景和矩形以及圓都繪製到canvas中。導致合成的圖有灰色的背景。
也就是說離屏繪製是像圖層一樣,先後擺放繪製。
具體小案例
pain效果相關 濾鏡
LightingColorFilter光照效果濾鏡
public LightingColorFilter (int mul, int add)
mul和add都是和顏色值格式相同的int值,其中mul用來和目標像素相乘,add用來和目標像素相加:
alpha通道將被忽略.
如果 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
R G B目標
R' 得到後的結果
使用:
/**
* R' = R * mul.R / 0xff + add.R 00
* G' = G * mul.G / 0xff + add.G ff
* B' = B * mul.B / 0xff + add.B ff
*/
//紅色去除掉
LightingColorFilter lighting = new LightingColorFilter(0x00ffff,0x000000);
mPaint.setColorFilter(lighting);
canvas.drawBitmap(mBitmap, 0,0, mPaint);
PorterDuffColorFilter濾鏡
使用一個指定的顏色和一種指定的 PorterDuff.Mode 來與繪製對象進行合成.
public PorterDuffColorFilter (int color, PorterDuff.Mode mode)
參數 | |
---|---|
color | 具體的顏色值 |
mode | 指定PorterDuff.Mode混合模式 |
PorterDuffColorFilter porterDuffColorFilter = new PorterDuffColorFilter(Color.RED, PorterDuff.Mode.DARKEN);
mPaint.setColorFilter(porterDuffColorFilter);
canvas.drawBitmap(mBitmap, 100, 0, mPaint);
ColorMatrixColorFilter
public ColorMatrixColorFilter (float[] array)
參數 | |
---|---|
array | 4*5列矩陣數組 |
使用
float[] colorMatrix = {
1,0,0,0,0, //red
0,1,0,0,0, //green
0,0,1,0,0, //blue
0,0,0,1,0 //alpha
};
mColorMatrixColorFilter = new ColorMatrixColorFilter(colorMatrix);
mPaint.setColorFilter(mColorMatrixColorFilter);
canvas.drawBitmap(mBitmap, 100, 0, mPaint);
ColorMatrix cm = new ColorMatrix();
//亮度調節,調節初始矩陣進行重新賦值
cm.setScale(1,2,1,1);
//
//飽和度調節0-無色彩, 1- 默認效果, >1飽和度加強
// cm.setSaturation(2);
//
// //色調調節
// cm.setRotate(0, 45);
//
mColorMatrixColorFilter = new ColorMatrixColorFilter(cm);
mPaint.setColorFilter(mColorMatrixColorFilter);
canvas.drawBitmap(mBitmap, 100, 0, mPaint);
參考:
https://hencoder.com/ui-1-2/
部分內容參考於網絡,無法找到原創標記。如果是你原創,請聯繫我添加。