Paint(畫筆)贴妻,Android中繪制界面最常見的一個(gè)類,它的設(shè)計(jì)思路其實(shí)也遵從現(xiàn)實(shí)中畫筆的定義:在畫布(Canvas)上繪制內(nèi)容的對(duì)象蝙斜。
我們通過設(shè)置Paint相關(guān)屬性名惩,就可以在畫布上繪制不同樣式的圖案。
1乍炉、常用API
函數(shù) | 解釋 |
---|---|
void setColor(int color) | 設(shè)置畫筆顏色 |
void setStyle(Style style) | 描邊效果绢片。 可選值包括 FILL 、FILL_AND_STROKE 岛琼、STROKE
|
void setStrokeWidth(float width) | 設(shè)置畫筆寬度底循,單位是px。 只在Style為 STROKE 和FILL_AND_STROKE 時(shí)有效 |
void setAntiAlias(boolean aa) | 抗鋸齒槐瑞,繪制不規(guī)則圖形使用熙涤,如果繪制矩形、位圖困檩,就不需要打開 |
void setDither(boolean dither) | 抗抖動(dòng) |
setStrokeMiter(float miter) | |
void setStrokeCap(Cap cap) | 線帽風(fēng)格祠挫。Cap.ROUND (圓形),Cap.SQUARE (方形),Cap.BUTT (無線帽)。 |
void setStrokeJoin(Join join) | 拐角風(fēng)格悼沿。Join.MITER (銳角),Join.ROUND (圓坏忍颉),Join.BEVEL (直線) |
void setFilterBitmap(boolean filter) | 雙線性濾波 |
注意:在Android系統(tǒng)在,顏色一般由一個(gè)int值表示:int color = (alpha<<24) | (red<<16) | (green<<8) | blue
2糟趾、文字相關(guān)API
2.1慌植、文字相關(guān)函數(shù)
函數(shù) | 解釋 |
---|---|
void setTextSize(float textSize) | 設(shè)置字體大小 |
void setTextAlign(Align align) | 設(shè)置文字對(duì)齊方式,包括LEFT 义郑、CENTER 蝶柿、RIGHT
|
void setFakeBoldText(boolean) | 設(shè)置是否為粗體 |
void setUnderlineText(boolean) | 設(shè)置下劃線 |
void setTextSkewX(float) | 設(shè)置字體水平傾斜度,普通斜體字設(shè)為-0.25 |
void setStrikeThruText(boolean) | 設(shè)置帶有刪除線效果 |
void setTextScaleX(2) | 水平縮放 |
2.2非驮、字體相關(guān)函數(shù)
1交汤、設(shè)置字體樣式
Typeface setTypeface(Typeface typeface)
typeface取值:Typeface.SANS_SERIF
、Typeface.MONOSPACE
劫笙、Typeface.SERIF
芙扎,但對(duì)中文支持不好星岗,一般都不使用。
2纵顾、根據(jù)字體樣式獲取對(duì)應(yīng)的默認(rèn)字體
Typeface defaultFromStyle(int style)
直接通過指定字體名來加載系統(tǒng)中自帶的字體樣式伍茄,如果字體樣式不存在栋盹,則返回系統(tǒng)樣式施逾。style
取值如下:
Typeface.NORMAL
: 正常字體。
Typeface.BOLD
: 粗體例获。
Typeface.ITALIC
: 斜體汉额。
Typeface.BOLD_ITALIC
: 粗斜體。
3榨汤、創(chuàng)建字體
3.1蠕搜、獲取系統(tǒng)自帶的字體
Typeface create(String familyName, int style)
3.2、獲取應(yīng)用Asset目錄下的字體
Typeface createFromAsset(AssetManager mgr, String path)
3.3收壕、從字體文件中獲得字體
Typeface createFromFile(String path)
Typeface createFromFile(File path)
2.3妓灌、文字的測量
1、文字的外接矩形
void getTextBounds(String text, int start, int end, Rect bounds)
注意蜜宪,這個(gè)矩形是根據(jù)基線位置為(0,0)得到的
2虫埂、測量文字寬度
float measureText(char[] text, int index, int count)
float measureText(String text, int start, int end)
float measureText(String text)
float measureText(CharSequence text, int start, int end)
3、文字的基線
文字的繪制位置圃验,不是由文字左上角位置所決定的掉伏,而是由文字的TextAlign
和baseline
所控制的:
- 當(dāng)TextAlign為
LEFT時(shí)
(默認(rèn)),繪制點(diǎn)為(x=文字開始位置澳窑,y=baseline)
- 當(dāng)TextAlign為
CENTER
時(shí)斧散,繪制點(diǎn)為(x=文字中心位置,y=baseline)
- 當(dāng)TextAlign為
RIGHT
時(shí)摊聋,繪制點(diǎn)為(x=文字結(jié)束位置鸡捐,y=baseline)
由此可見,繪制文字的關(guān)鍵麻裁,在于找到baseline
箍镜,這時(shí)就要用到Paint.getFontMetrics()
函數(shù)了,該函數(shù)返回一個(gè)FontMetrics
對(duì)象悲立,其中包含以下變量:
變量 | 含義 |
---|---|
ascent | 字體最佳繪制區(qū)域頂部到baseline的距離 |
top | 字體最大繪制區(qū)域頂部到baseline的距離 |
descent | 字體最佳繪制區(qū)域底部到baseline的距離 |
bottom | 字體最大繪制區(qū)域底部到baseline的距離 |
leading | 上一行字符的descent到下一行的ascent之間的距離 |
它們與baseline
的位置關(guān)系如圖所示:
我們通過FontMetrics
鹿寨,能夠很快的計(jì)算出baseLine
。注意薪夕,由于坐標(biāo)系的關(guān)系脚草,F(xiàn)ontMetrics的bottom為正數(shù),top為負(fù)數(shù)原献。
3馏慨、高級(jí)
3.1埂淮、setShadowLayer
如果需要給TextView的文字添加陰影,有兩種方式:
1写隶、xml布局中設(shè)置
shadowRadius
倔撞、shadowDx
、shadowDy
慕趴、shadowColor
這4個(gè)屬性
2痪蝇、調(diào)用TextView的setShadowLayer方法。
這里我們介紹第二種冕房,setShadowLayer
可以在當(dāng)前圖層下方繪制一個(gè)陰影圖層躏啰,并具有指定的偏移量和顏色以及模糊半徑。
void setShadowLayer(float radius, float dx, float dy, int shadowColor)
參數(shù)含義:
radius
:陰影模糊半徑
dx
和dy
:陰影位置偏移
shadowColor
:陰影顏色
注意:
設(shè)置setShadowLayer后耙册,繪制Bitmap的陰影效果會(huì)有所不同(也跟系統(tǒng)版本
相關(guān)):
1给僵、如果Bitmap是彩色不透明圖像,如由jpg圖片獲取的Bitmap
陰影由Bitmap模糊后加上shadowColor的alpha得到详拙。
2帝际、如果Bitmap是單色不透明圖像,如由jpg圖片獲取的Bitmap饶辙,并調(diào)用Bitmap.extractAlpha()
陰影由shadowColor模糊而來蹲诀。
3、如果Bitmap是彩色透明圖像畸悬,如由png圖片獲取的Bitmap
1侧甫、陰影不會(huì)被模糊
2、陰影由Bitmap和shadowColor的alpha得到蹋宦。
4披粟、如果Bitmap是單色透明圖像,如由png圖片獲取的Bitmap冷冗,并調(diào)用Bitmap.extractAlpha()
1守屉、陰影不會(huì)被模糊
2、陰影顏色是shadowColor蒿辙。
總結(jié):
1拇泛、如果圖片帶有透明通道,陰影將不會(huì)被模糊思灌,并受shadowColor的alpha值影響俺叭。
2、如果圖片是單色泰偿,陰影將由shadowColor決定熄守。
當(dāng)不再需要陰影時(shí),可以通過將radius設(shè)置為0,或者調(diào)用clearShadowLayer
來清除陰影裕照。
3.2攒发、setMaskFilter
MaskFilter setMaskFilter(MaskFilter maskfilter)
MaskFilter有2個(gè)子類:
- BlurMaskFilter:模糊效果
- EmbossMaskFilter:浮雕效果
其中BlurMaskFilter構(gòu)造函數(shù)
public BlurMaskFilter(float radius, Blur style)
需要指定模糊半徑,和模糊類型:
模糊類型 | 含義 |
---|---|
NORMAL | 內(nèi)外都模糊 |
SOLID | 內(nèi)部直接繪制晋南,外部模糊 |
OUTER | 內(nèi)部不繪制惠猿,外部模糊 |
INNER | 模糊內(nèi)部,外部不繪制 |
注意
:使用BlurMaskFilter
模糊Bitmap時(shí)负间,也有跟setShadowLayer
一樣的限制偶妖,只有當(dāng)Bitmap不透明,才會(huì)有模糊效果唉擂。那如何生成一個(gè)帶透明度的純色陰影圖片呢餐屎?
可通過設(shè)置BlurMaskFilter檀葛,再調(diào)用Bitmap extractAlpha(Paint paint, int[] offsetXY)
方法即可玩祟。
public class ShadowView extends View {
private Paint mPaint = new Paint();
private Bitmap mAlphaBitmap;
public ShadowView(Context context) {
super(context);
setLayerType(LAYER_TYPE_SOFTWARE, null);
mPaint.setColor(Color.BLACK);
mPaint.setTextSize(40);
// mPaint.setShadowLayer(10, 10, 10, Color.argb(255, 255, 0, 0));
mPaint.setMaskFilter(new BlurMaskFilter(10, BlurMaskFilter.Blur.NORMAL));
Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.cat_dog);
mAlphaBitmap = Bitmap.createScaledBitmap(bitmap, 400, 400, true).extractAlpha(mPaint, new int[]{10, 10});
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
canvas.drawColor(Color.WHITE);
canvas.drawText("青云", 140, 200, mPaint);
canvas.drawCircle(150, 400, 50, mPaint);
canvas.saveLayerAlpha(new RectF(400, 50, 400 + mAlphaBitmap.getWidth(), 50 + +mAlphaBitmap.getHeight()), 100);
canvas.drawBitmap(mAlphaBitmap, 400, 50, mPaint);
canvas.restore();
}
}
3.3、setPathEffect
setPathEffect(PathEffect effect)
public class EffectView extends View {
private PathEffect[] mEffect = new PathEffect[6];
private Path mPath = new Path();
private Paint mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
public EffectView(Context context) {
super(context);
for (int i = 0; i <= 30; i++) {
mPath.lineTo(i * 35, (float) (Math.random() * 100));
}
mEffect[0] = null;
mEffect[1] = new CornerPathEffect(30);
mEffect[2] = new DiscretePathEffect(3.0F, 5.0F);
mEffect[3] = new DashPathEffect(new float[]{20, 10, 5, 10}, 0);
Path path = new Path();
path.addRect(0, 0, 8, 8, Path.Direction.CCW);
mEffect[4] = new PathDashPathEffect(path, 12, 0, PathDashPathEffect.Style.ROTATE);
mEffect[5] = new ComposePathEffect(mEffect[3], mEffect[1]);
mPaint.setStyle(Paint.Style.STROKE);
mPaint.setColor(Color.BLUE);
}
@Override
protected void onDraw(Canvas canvas) {
for (PathEffect pathEffect : mEffect) {
mPaint.setPathEffect(pathEffect);
canvas.drawPath(mPath, mPaint);
canvas.translate(0, 150);
}
}
}
3.4屿聋、setShader
Shader setShader(Shader shader)
參數(shù):Shader 著色器對(duì)象,一般使用系統(tǒng)所提供的幾個(gè)子類:
LinearGradient
:線性渲染(霓虹燈文字空扎,倒影圖片)
RadialGradient
:環(huán)形渲染(水波紋效果)
SweepGradient
:掃描渲染(雷達(dá)掃描效果)
BitmapShader
:位圖渲染
ComposeShader
:組合渲染,例如LinearGradient+BitmapShader
public BitmapShader(Bitmap bitmap, TileMode tileX, TileMode tileY)
TileMode取值如下:
TileMode取值 | 含義 |
---|---|
TileMode.CLAMP | 用邊緣像素來填充多余空間 |
TileMode.REPEAT | 重復(fù)原圖像來填充多余空間 |
TileMode.MIRROR | 使用鏡像圖像來填充多余空間 |
注意:填充順序?yàn)橄蓉Q向填充润讥,再橫向填充转锈,并且繪制是從左上角進(jìn)行繪制,與畫筆位置無關(guān)楚殿。
所以這會(huì)照成一些問題撮慨,如:
1、單個(gè)圖像不能充滿整個(gè)屏幕
2脆粥、單個(gè)圖像不能在控件中部位置完整顯示
解決方案為:Shader.setLocalMatrix
3.5砌溺、setColorFilter
ColorFilter setColorFilter(ColorFilter filter)
設(shè)置顏色過濾,一般使用ColorFilter的三個(gè)子類
LightingColorFilter:光照效果
PorterDuffColorFilter:指定一個(gè)顏色和一種PorterDuff.Mode與繪制對(duì)象進(jìn)行組合
ColorMatrixColorFilter:使用一個(gè)ColorMatrix來對(duì)顏色進(jìn)行處理
ColorMatrix類
ColorMatrix.setScale //色度調(diào)節(jié)
ColorMatrix.setSaturation //飽和度調(diào)節(jié)变隔,0-無色彩规伐,1-默認(rèn)效果,>1飽和度加強(qiáng)
ColorMatrix.setRotate //色調(diào)調(diào)節(jié)
常見效果:
- 平移運(yùn)算---加法
ColorMatrix colorMartrix = new ColorMatrix(new float[]{
1, 0, 0, 0, 0,
0, 1, 0, 0, 100,
0, 0, 1, 0, 0,
0, 0, 0, 1, 0,
});
- 反相效果 -- 底片效果
ColorMatrix colorMartrix = new ColorMatrix(new float[]{
-1, 0, 0, 0, 255,
0, -1, 0, 0, 255,
0, 0, -1, 0, 255,
0, 0, 0, 1, 0,
});
- 縮放運(yùn)算---乘法 -- 顏色增強(qiáng)
ColorMatrix colorMartrix = new ColorMatrix(new float[]{
1.2f, 0, 0, 0, 0,
0, 1.2f, 0, 0, 0,
0, 0, 1.2f, 0, 0,
0, 0, 0, 1.2f, 0,
});
- 黑白照片
將三通道變?yōu)閱瓮ǖ赖幕叶饶J?br> 原理:只要把R G B 三通道的色彩信息設(shè)置成一樣匣缘,那么圖像就會(huì)變成灰色猖闪,同時(shí)為了保證圖像亮度不變,同一個(gè)通道里的R+G+B =1
ColorMatrix colorMartrix = new ColorMatrix(new float[]{
0.213f, 0.715f, 0.072f, 0, 0,
0.213f, 0.715f, 0.072f, 0, 0,
0.213f, 0.715f, 0.072f, 0, 0,
0, 0, 0, 1, 0,
});
- 發(fā)色效果---(比如紅色和綠色交換)
ColorMatrix colorMartrix = new ColorMatrix(new float[]{
1, 0, 0, 0, 0,
0, 0, 1, 0, 0,
0, 1, 0, 0, 0,
0, 0, 0, 0.5F, 0,
});
- 復(fù)古效果
ColorMatrix colorMartrix = new ColorMatrix(new float[]{
1 / 2f, 1 / 2f, 1 / 2f, 0, 0,
1 / 3f, 1 / 3f, 1 / 3f, 0, 0,
1 / 4f, 1 / 4f, 1 / 4f, 0, 0,
0, 0, 0, 1, 0,
});
3.6肌厨、setXfermode
混合模式是Paint繪圖中最難的部分培慌,它能夠?qū)蓮垐D片無縫結(jié)合,實(shí)現(xiàn)類似Photoshop中的兩張圖片融合效果柑爸。
Xfermode setXfermode(Xfermode xfermode)
Xfermode是一個(gè)空類吵护,PorterDuffXfermode
是其唯一的子類。
在介紹Xfermode之前,我們先介紹一下PorterDuff.Mode
和離屏渲染
相關(guān)知識(shí)何址。