我們可以通過(guò)Paint中setter方法來(lái)為畫筆設(shè)置屬性: 浩浩蕩蕩來(lái)將這些方法一一過(guò)一遍: setvoid set(Paint src) 為當(dāng)前畫筆copy一個(gè)畫筆 setARGBvoid setARGB(int a, int r, int g, int b) 設(shè)置Paint對(duì)象顏色,a代表透明度,r,g,b代表顏色值
一般在xml里定義顏色可以直接寫: android:textColor='#FF6281' 但是在code代碼中就必須寫成這樣: text.setTextColor(0xffff6281); xml中透明度寫不寫無(wú)所謂,默認(rèn)是ff不透明,但是代碼中用十六進(jìn)制0x來(lái)表示,就必須跟上ff透明度,不然會(huì)默認(rèn)00全透明。 setAlphavoid setAlpha(int a) 設(shè)置alpha透明度,范圍為0~255 setAntiAliasvoid setAntiAlias(boolean aa) 是否抗鋸齒 setColorvoid setColor(int color) 設(shè)置paint顏色 setColorFilterColorFilter setColorFilter (ColorFilter filter) 設(shè)置顏色過(guò)濾,ColorFilter有三個(gè)子類去實(shí)現(xiàn)ColorMatrixColorFilter、LightingColorFilter和PorterDuffColorFilter ColorMatrixColorFilterpublic class PaintCanvas extends View {
private Paint mPaint;
//省略構(gòu)造方法
private void init() {
mPaint = new Paint();
mPaint.setAntiAlias(true);
// 生成色彩矩陣
ColorMatrix colorMatrix = new ColorMatrix(new float[]{
0.5F, 0, 0, 0, 0,
0, 0.5F, 0, 0, 0,
0, 0, 0.5F, 0, 0,
0, 0, 0, 1, 0,
});
mPaint.setColorFilter(new ColorMatrixColorFilter(colorMatrix));
}
@Override
protected void onDraw(Canvas canvas) {
Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.mipmap.logo);
canvas.drawBitmap(bitmap, 0, 0, mPaint);
}
} 第一行表示的R(紅色)的向量,第二行表示的G(綠色)的向量,第三行表示的B(藍(lán)色)的向量,最后一行表示A(透明度)的向量,這一順序必須要正確不能混淆!這個(gè)矩陣不同的位置表示的RGBA值,其范圍在0.0F至2.0F之間,1為保持原圖的RGB值。每一行的第五列數(shù)字表示偏移值。 這是原圖效果,增加ColorMatrix,效果如下: LightingColorFilter只有一個(gè)構(gòu)造方法, // 設(shè)置顏色過(guò)濾,去掉綠色
mPaint.setColorFilter(new LightingColorFilter(0xFFFF00FF, 0x00000000)); 效果如下: PorterDuffColorFilter也只有一個(gè)構(gòu)造方法, // 設(shè)置顏色過(guò)濾,Color的值設(shè)為紅色,模式PorterDuff.Mode.DARKEN變暗
mPaint.setColorFilter(new PorterDuffColorFilter(Color.RED, PorterDuff.Mode.DARKEN)); 效果如下: setDithervoid setDither(boolean dither) 設(shè)定是否使用圖像抖動(dòng)處理,會(huì)使繪制出來(lái)的圖片顏色更加平滑和飽滿,圖像更加清晰 setFakeBoldTextvoid setFakeBoldText(boolean fakeBoldText) 設(shè)置偽粗體文本 setFilterBitmapvoid setFilterBitmap(boolean filter) 設(shè)置位圖進(jìn)行濾波處理 setHintingvoid setHinting (int mode) Added in API level 14,設(shè)置暗示模式,HINTING_OFF 或 HINTING_ON setLetterSpacingvoid setLetterSpacing (float letterSpacing) Added in API level 21,設(shè)置文本字母間距,默認(rèn)0,負(fù)值收緊文本 setLinearTextvoid setLinearText(boolean linearText) 設(shè)置線性文本 setMaskFilterMaskFilter setMaskFilter (MaskFilter maskfilter) 設(shè)置濾鏡的效果,MaskFilter有兩個(gè)子類實(shí)現(xiàn)BlurMaskFilter, EmbossMaskFilter BlurMaskFilter設(shè)置畫筆模糊陰影效果 mPaint.setMaskFilter(new BlurMaskFilter(20f, BlurMaskFilter.Blur.SOLID)); 參數(shù)1:模糊延伸半徑,必須>0; 四種枚舉效果如下: EmbossMaskFilter//Paint的setMaskFilter不被GPU支持,為了確保畫筆的setMaskFilter能供起效,我們需要禁用掉GPU硬件加速或AndroidManifest.xml文件中設(shè)置android:hardwareAccelerated為false
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
//View從API Level 11才加入setLayerType方法
//設(shè)置軟件渲染模式繪圖
this.setLayerType(View.LAYER_TYPE_SOFTWARE, null);
}
//設(shè)置浮雕濾鏡效果,參數(shù)1:光源指定方向;參數(shù)2:環(huán)境光亮度,取值0-1,值越小越暗;參數(shù)3:鏡面高光反射系數(shù),值越小反射越強(qiáng);參數(shù)4:模糊延伸半徑
mPaint.setMaskFilter(new EmbossMaskFilter(new float[]{1, 1, 1}, 0.4f, 8f, 3f)); 效果如下: setPathEffectPathEffect setPathEffect(PathEffect effect) 設(shè)置路徑效果,PathEffect有6個(gè)子類實(shí)現(xiàn)ComposePathEffect, CornerPathEffect, DashPathEffect, DiscretePathEffect, PathDashPathEffect, SumPathEffect public class PaintCanvas extends View {
private Paint mPaint;
// 路徑對(duì)象
private Path mPath;
private PathEffect[] pathEffects = new PathEffect[7];
private float mPhase=5;
//省略構(gòu)造方法
private void init() {
mPaint = new Paint();
mPaint.setStyle(Paint.Style.STROKE);
mPaint.setStrokeWidth(5);
mPaint.setAntiAlias(true);
initPath();
}
private void initPath() {
// 實(shí)例化路徑
mPath = new Path();
// 定義路徑的起點(diǎn)
mPath.moveTo(10, 50);
// 定義路徑的各個(gè)點(diǎn)
for (int i = 0; i <= 30; i ) {
mPath.lineTo(i * 35, (float) (Math.random() * 100));
}
//什么都不處理
pathEffects[0] = null;
//參數(shù)1:線段之間的圓滑程度
pathEffects[1] = new CornerPathEffect(10);
//參數(shù)1:間隔線條長(zhǎng)度(length>=2),如float[] {20, 10}的偶數(shù)參數(shù)20定義了我們第一條實(shí)線的長(zhǎng)度,
//而奇數(shù)參數(shù)10則表示第一條虛線的長(zhǎng)度,后面不再有數(shù)據(jù)則重復(fù)第一個(gè)數(shù)以此往復(fù)循環(huán);參數(shù)2:虛實(shí)線間距
pathEffects[2] = new DashPathEffect(new float[]{20, 10}, mPhase);
//參數(shù)1:值越小雜點(diǎn)越密集;參數(shù)2:雜點(diǎn)突出的大小,值越大突出的距離越大
pathEffects[3] = new DiscretePathEffect(5.0f, 10.0f);
Path path = new Path();
path.addRect(0, 0, 8, 8, Path.Direction.CCW);
//定義路徑虛線的樣式,參數(shù)1:path;參數(shù)2:實(shí)線的長(zhǎng)度;參數(shù)3:虛實(shí)線間距
pathEffects[4] = new PathDashPathEffect(path, 20, mPhase, PathDashPathEffect.Style.ROTATE);
pathEffects[5] = new ComposePathEffect(pathEffects[2], pathEffects[4]);
//ComposePathEffect和SumPathEffect都可以用來(lái)組合兩種路徑效果,具體區(qū)別(不知道如何描述)小伙伴們自己試試
pathEffects[6] = new SumPathEffect(pathEffects[4], pathEffects[3]);
}
@Override
protected void onDraw(Canvas canvas) {
/*
* 繪制路徑
*/
for (int i = 0; i < pathEffects.length; i ) {
mPaint.setPathEffect(pathEffects[i]);
canvas.drawPath(mPath, mPaint);
// 每繪制一條將畫布向下平移250個(gè)像素
canvas.translate(0, 250);
}
}
} 效果如下: setRasterizerRasterizer setRasterizer(Rasterizer rasterizer) setShaderShader setShader(Shader shader) 設(shè)置著色器,Shader 子類實(shí)現(xiàn)有BitmapShader, ComposeShader, LinearGradient, RadialGradient, SweepGradient BitmapShader對(duì)圖形進(jìn)行渲染,構(gòu)造方法: BitmapShader (Bitmap bitmap,Shader.TileMode tileX,Shader.TileMode tileY) tileX、tileY參數(shù)Shader.TileMode有三個(gè): 設(shè)置tileX、tileY為Shader.TileMode.CLAMP public class PaintCanvas extends View {
private Paint mPaint;
private Context mContext;
private Bitmap mBitmap;
private BitmapShader mShader;
// 省略構(gòu)造方法
private void init() {
mBitmap = BitmapFactory.decodeResource(mContext.getResources(), R.mipmap.logo);
mShader= new BitmapShader(mBitmap, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP);
mPaint = new Paint();
mPaint.setAntiAlias(true);
}
@Override
protected void onDraw(Canvas canvas) {
mPaint.setShader(mBitmapShader);
canvas.drawCircle(500, 550, 500, mPaint);
}
} 效果如下: 設(shè)置tileX、tileY為Shader.TileMode.MIRROR 設(shè)置tileX、tileY為Shader.TileMode.REPEAT LinearGradient設(shè)置線性漸變效果,有兩個(gè)構(gòu)造函數(shù) //坐標(biāo)(x0,y0)漸變直線的起點(diǎn),坐標(biāo)(x1,y1)漸變直線的終點(diǎn),color0和color1分別表示了漸變的起始顏色和終止顏色,TileMode也有CLAMP 、REPEAT 和 MIRROR三個(gè)取值
LinearGradient(float x0, float y0, float x1, float y1, int color0, int color1, Shader.TileMode tile)
LinearGradient(float x0, float y0, float x1, float y1, int[] colors, float[] positions,Shader.TileMode tile) 例子: public class PaintCanvas extends View {
private Paint mPaint;
private Context mContext;
private Bitmap mBitmap;
private Shader mShader;
// 省略構(gòu)造方法
private void init() {
mShader = new LinearGradient(0, 0, 500, 500, Color.BLUE, Color.GREEN,Shader.TileMode.CLAMP);
mPaint = new Paint();
mPaint.setAntiAlias(true);
}
@Override
protected void onDraw(Canvas canvas) {
mPaint.setShader(mBitmapShader);
canvas.drawCircle(500, 550, 400, mPaint);
}
} 效果如下: RadialGrdient設(shè)置光束從中心向四周發(fā)散的輻射漸變效果,構(gòu)造方法: //坐標(biāo)(centerX,centerY)中心點(diǎn)坐標(biāo),radius圓的半徑,centerColor中心顏色,edgeColor圓的輪廓顏色,顏色逐漸從centerColor漸變到edgeColor,TileMode也有CLAMP 、REPEAT 和 MIRROR三個(gè)取值
RadialGradient(float centerX, float centerY, float radius, int centerColor, int edgeColor, Shader.TileMode tileMode)
RadialGradient(float centerX, float centerY, float radius, int[] colors, float[] stops, Shader.TileMode tileMode) 例子: public class PaintCanvas extends View {
private Paint mPaint;
private Context mContext;
private Shader mShader;
// 省略構(gòu)造方法
private void init() {
mShader = new RadialGradient(500, 500, 400, Color.BLUE, Color.GREEN, Shader.TileMode.CLAMP);
mPaint = new Paint();
mPaint.setAntiAlias(true);
}
@Override
protected void onDraw(Canvas canvas) {
mPaint.setShader(mBitmapShader);
canvas.drawCircle(500, 550, 400, mPaint);
}
} 效果如下: SweepGradient設(shè)置繞著某中心點(diǎn)進(jìn)行360度旋轉(zhuǎn)漸變效果,構(gòu)造方法: //坐標(biāo)(cx,cy)決定了中心點(diǎn)的位置,會(huì)繞著該中心點(diǎn)進(jìn)行360度旋轉(zhuǎn)。color0表示的是起點(diǎn)的顏色,color1表示的是終點(diǎn)的顏色
SweepGradient(float cx, float cy, int color0, int color1)
//坐標(biāo)(cx,cy)決定了中心點(diǎn)的位置,colors顏色數(shù)組,position取值范圍為[0,1],0和1都表示3點(diǎn)鐘位置,0.25表示6點(diǎn)鐘位置,0.5表示9點(diǎn)鐘位置,0.75表示12點(diǎn)鐘位置,諸如此類
SweepGradient(float cx, float cy, int[] colors, float[] positions) 例子: public class PaintCanvas extends View {
private Paint mPaint;
private Context mContext;
private Shader mShader;
// 省略構(gòu)造方法
private void init() {
mShader = new SweepGradient(500, 500, Color.BLUE, Color.GREEN);
mPaint = new Paint();
mPaint.setAntiAlias(true);
}
@Override
protected void onDraw(Canvas canvas) {
mPaint.setShader(mBitmapShader);
canvas.drawCircle(500, 550, 400, mPaint);
}
} 效果如下: ComposeShader混合,有兩個(gè)構(gòu)造函數(shù) //shaderA對(duì)應(yīng)下層圖形,shaderB對(duì)應(yīng)上層圖形
ComposeShader(Shader shaderA, Shader shaderB, Xfermode mode)
ComposeShader(Shader shaderA, Shader shaderB, PorterDuff.Mode mode) 例子: public class PaintCanvas extends View {
private Paint mPaint;
private Context mContext;
private Bitmap mBitmap;
private Shader bitmapShader, linearGradient, composeShader;
// 省略構(gòu)造方法
private void init() {
mBitmap = BitmapFactory.decodeResource(mContext.getResources(), R.mipmap.logo);
bitmapShader = new BitmapShader(mBitmap, Shader.TileMode.MIRROR, Shader.TileMode.MIRROR);
linearGradient = new LinearGradient(0, 0, mBitmap.getWidth(), mBitmap.getHeight(), Color.BLUE, Color.GREEN, Shader.TileMode.CLAMP);
//bitmapShader對(duì)應(yīng)下層圖形,linearGradient對(duì)應(yīng)上層圖形,像素顏色混合采用MULTIPLY模式
composeShader = new ComposeShader(bitmapShader, linearGradient, PorterDuff.Mode.MULTIPLY);
mPaint = new Paint();
mPaint.setAntiAlias(true);
}
@Override
protected void onDraw(Canvas canvas) {
mPaint.setShader(mBitmapShader);
canvas.drawCircle(500, 550, 400, mPaint);
}
} 效果如下: setShadowLayervoid setShadowLayer(float radius, float dx, float dy, int shadowColor) 圖形添加一個(gè)陰影層效果 setStrikeThruTextvoid setStrikeThruText (boolean strikeThruText) 設(shè)置刪除線 setStrokeCapvoid setStrokeCap (Paint.Cap cap) 當(dāng)設(shè)置setStyle是Stroke或StrokeAndFill,設(shè)置筆刷的圖形樣式,如圓形樣式Cap.ROUND或方形樣式Cap.SQUARE setStrokeJoinvoid setStrokeJoin (Paint.Join join) 當(dāng)設(shè)置setStyle是Stroke或StrokeAndFill,設(shè)置繪制時(shí)各圖形的結(jié)合方式,如影響矩形角的外輪廓 setStrokeMitervoid setStrokeMiter (float miter) 當(dāng)設(shè)置setStyle是Stroke或StrokeAndFill,設(shè)置斜切 setStrokeWidthvoid setStrokeWidth (float width) 當(dāng)畫筆樣式為STROKE或FILL_OR_STROKE時(shí),設(shè)置筆刷的粗細(xì)度 setStylevoid setStyle (Paint.Style style) 設(shè)置畫筆樣式,畫筆樣式分三種: setSubpixelTextvoid setSubpixelText (boolean subpixelText) 有助于文本在LCD屏幕上的顯示效果 setTextAlignvoid setTextAlign(Paint.Align align) 設(shè)置文本對(duì)齊 setTextScaleXvoid setTextScaleX(float scaleX) 設(shè)置文本縮放倍數(shù),1.0f為原始 setTextSizevoid setTextSize(float textSize) 設(shè)置字體大小 setTextSkewXvoid setTextSkewX (float skewX) 設(shè)置斜體文字,skewX為傾斜弧度,默認(rèn)值0,大于0,向左斜,小于0,向右斜 setTypefaceTypeface setTypeface(Typeface typeface) 設(shè)置字體,Typeface包含了字體的類型,粗細(xì),還有傾斜、顏色等。 mPaint.setTypeface(Typeface.SANS_SERIF); setUnderlineTextvoid setUnderlineText(boolean underlineText) 設(shè)置下劃線 setXfermodeXfermode setXfermode (Xfermode xfermode) 設(shè)置圖像混合模式,Xfermode 有個(gè)子類去實(shí)現(xiàn)PorterDuffXfermode PorterDuffXfermode構(gòu)造方法 Dst:先畫(下層)的圖形;Src:后畫(上層)的圖形,然而被網(wǎng)上這張圖片誤導(dǎo)了,解釋見孫群博客,他也給了最終運(yùn)行效果: 我一一運(yùn)行確實(shí)是如此,這里貼出Mode 為Screen代碼: public class PaintCanvas extends View {
private Paint mPaint;
private PorterDuffXfermode porterDuffXfermode;// 圖形混合模式
private Context mContext;
private Bitmap mBitmap;
//省略構(gòu)造方法
private void init() {
mBitmap = BitmapFactory.decodeResource(mContext.getResources(), R.mipmap.logo);
mPaint = new Paint();
mPaint.setAntiAlias(true);
// 實(shí)例化混合模式
porterDuffXfermode = new PorterDuffXfermode(PorterDuff.Mode.SCREEN);
}
@Override
protected void onDraw(Canvas canvas) {
int canvasWidth = canvas.getWidth();
int canvasHeight = canvas.getHeight();
//新建一個(gè)layer,放置在canvas默認(rèn)layer的上部,產(chǎn)生的layer初始時(shí)是完全透明的
int layerId = canvas.saveLayer(0, 0, canvasWidth, canvasHeight, null, Canvas.ALL_SAVE_FLAG);
//dst是先畫的圖形
canvas.drawBitmap(mBitmap, 0, 0, mPaint);
//設(shè)置混合模式
mPaint.setXfermode(porterDuffXfermode);
//src是后畫的圖形
mPaint.setColor(0xFFFFCC44);
canvas.drawCircle(600, 600, 200, mPaint);
//還原混合模式
mPaint.setXfermode(null);
//或canvas.restore()把這個(gè)layer繪制到canvas默認(rèn)的layer上去
canvas.restoreToCount(layerId);
}
} 例子源碼https://github.com/WuXiaolong/AndroidSamples/blob/master/app/src/main/java/com/wuxiaolong/androidsamples/paintcanvas/PaintCanvas.java 最后這篇文章真長(zhǎng),從開始寫到最后的校對(duì),花了很長(zhǎng)時(shí)間,每段代碼運(yùn)行都截圖上傳。只能說(shuō)實(shí)踐是檢驗(yàn)真理的唯一標(biāo)準(zhǔn),不一定知道每個(gè)原理,都必須知道每個(gè)是什么樣子的效果,記錄完成方便自己日后查找,也方便大家哦,如果您能讀到這篇文章的話。最后的最后,薩摩耶有話說(shuō):我只想安靜做一只可愛的狗狗! 鳴謝官網(wǎng)Paint
|
|