FontMatrics部分参考:http://mikewang.blog.51cto.com/3826268/871765
核心类
1.Canvas 画布
2.Bitmap 纸
3.Paint 笔
4.{
FontMetrics
PorterDuffXfermode
Matrix(3x3矩阵)
ColorMatrix(4x5矩阵)
ColorFilter
Shader
PathEffect
}
5. SurfaceView P155,有固定模版用法
思想
1.一般初始化Canvas时,要传入一个Bitmap,之后的所有的绘制效果都将呈现在Bitmap上。
Bitmap mPaper = Bitmap.createBitmap(bm.getWidth(), bm.getHeight(), Bitmap.Config.ARGB_8888);
mCanvas = new Canvas(mPaper);
mCanvas.drawBitmap(bm, 0, 0, paint);//将bm用画笔paint画到mPager上
2.在onDraw(canvas)方法中,只需要将步骤1中的纸mPaper绘制到系统提供的画布canvas上即可。
canvas.drawBitmap(mPaper, 0, 0, null);
3.Paint
具有非常强大的功能:
1)PorterDuffXfermode 滤镜功能:
mPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN));
mPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_OUT));
设置混合模式,具体效果参考文档,或Android群英传P146.
2)获取FontMetrics,测量文本尺寸
Paint.FontMetrics fm = mPaint.getFontMetrics();
FontMetrics属性:{
1. 基准点是baseline
2. ascent是baseline之上至字符最高处的距离
3. descent是baseline之下至字符最低处的距离
4. leading文档说的很含糊,其实是上一行字符的descent到下一行的ascent之间的距离
5. top指的是指的是最高字符到baseline的值,即ascent的最大值
6. 同上,bottom指的是最下字符到baseline的值,即descent的最大值
说明:ascent/descent/top/bottom,这几个值均表示距离baseline的距离。举例:ascent的值,即为字符最高处的y坐标减去baseline的y坐标之差。所以,其永远为负值。同理,descent/bottom永远为正值。
}
float baseY = - fm.top;
mCanvas.drawText("cuncaojin", 0, baseY, mPaint);
![](http://img1.51cto.com/attachment/201205/204735397.png)
3)Style(空心/实心)
mPaint.setStyle(Paint.Style.FILL);
mPaint.setStyle(Paint.Style.STROKE);
mPaint.setStyle(Paint.Style.FILL_AND_STROKE);
4)setColorFilter
ColorMatrix imageMatrix = new ColorMatrix();
//颜色矩阵,可以设置色调、饱和度、亮度
imageMatrix.setRotate(0/1/2,hue);//0,1,2——R,G,B 色调
imageMatrix.setSaturation(saturation);//饱和度为0时,图像为灰度图像
imageMatrix.setScale(lum, lum, lum, 1);//亮度
imageMatrix.postConcat(anotherColorMatrix);//将颜色矩阵叠加
paint.setColorFilter(new ColorMatrixColorFilter(imageMatrix));
5)setShader():主要作用是作为遮罩层,产生特殊效果
Shader(渲染器)类实现类有{
a. BitmapShader 位图Shader (相比其他Shader比较特殊)
{
用BitmapShader填充时的3种模式:
CLAMP 拉伸
REPEAT 重复
MIRROR 镜像
}
b. LinearGradient 线性Shader
c. RadialGradient 光束Shader
d. SweepGradient 梯度Shader
e. ComposeShader 混合Shader
}
6)setPathEffect 路径效果
a. null
b. CornerPathEffect 路径圆滑处理
c. DiscretePathEffect 产生杂点
d. DashPathEffect 虚线化
e. PathDashPathEffect 可设置虚线图形
f. ComposePathEffect 可组合以上效果
7)其他属性{
setAntiAlias(true); 抗锯齿
setStrokeJoin(Paint.Join.ROUND); 设置笔连接处圆滑处理
setStrokeCap(Paint.Cap.ROUND); 设置笔触圆滑处理
setStrokeWidth(50); 设置笔宽
setColor();
setARGB();
setAlpah();
setTextSize();
}
4.Canvas
1)绘制{
drawPoint
drawLine
drawRect
drawRoundRect
drawArc 绘制扇形或弧形(由参数useCenter决定,true扇形,false弧形,设置Paint.Style决定是空心还是实心)
drawOval 绘制椭圆
drawText
drawPosText(text, new float[]{x1,y1,x2,y2,...xn,yn}, paint) 在指定位置逐个对每个字符绘制
drawPath 绘制路径
drawBitmap
}
2)结合Matrix
Matrix matrix = new Matrix();
matrix{
setRotate()
setTranslate();
setScale();
setSkew(); 错切变换/剪切变换
pre() 先乘
post() 后乘
}
canvas.drawBitmap(mBitmap, matrix ,null);
---------------------------------------------
Canvas mCanvas = new Canvas(mBmp);
Matrix matrix = new Matrix();
float scale = w * 1f / getResources().getDisplayMetrics().widthPixels;
matrix.setScale(scale, scale);
mCanvas.drawBitmap(bitmap, matrix, mPaint);
3)Canvas的其他方法{
save() 将之前绘制的所有图像进行保存
restore() 将save()之后绘制的所有图像与save()之前的图像进行合并
translate()
rotate()
}
Demo:
自定义一个圆形图,实现方案{
1)使用paint.setXferMode(new PorterXferMode(...))
a. 绘制圆
b. 对画笔设置PorterDuffXfermode(SRC_IN)则上步绘制的圆作为遮罩层
c. (设置缩放比例等)优化绘图效果
d. 绘制图片
2) 使用paint.setShader(new BitmapShader(...))
a. 对画笔设置渲染器为BitmapShader,模式选择拉伸
mPaint.setShader(new BitmapShader(mBmp, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP));
b. (设置缩放比例等)优化绘图效果
c. 绘制圆
}
参考代码如下:
方案一:
public CircleView(Context context, AttributeSet attrs) {
super(context, attrs);
init();
TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.CircleView);
int indexCount = typedArray.getIndexCount();
for (int i = 0; i < indexCount; i++) {
int index = typedArray.getIndex(i);
switch (index) {
case R.styleable.CircleView_src:
BitmapDrawable drawable = (BitmapDrawable) typedArray.getDrawable(index);
mBitmap = drawable.getBitmap();
break;
}
}
typedArray.recycle();
}
private void init() {
mPaint = new Paint();
mPaint.setAntiAlias(true);
mPaint.setStrokeJoin(Paint.Join.ROUND);
}
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
mPaper = Bitmap.createBitmap(w, w, Bitmap.Config.ARGB_8888);
mCanvas = new Canvas(mPaper);
mPaint.setTextSize(50);
mPaint.setStrokeWidth(5);
mPaint.setARGB(255, 255, 0, 0);
mPaint.setColor(0xff00ff00);
mPaint.setTextAlign(Paint.Align.LEFT);
Paint.FontMetrics fm = mPaint.getFontMetrics();
Log.i("tag", fm.ascent + ", leading:" + fm.leading + " ,descent:" + fm.descent + ", bottom:" + fm.bottom + ", " + fm.top);
float baseY = -fm.ascent;
mCanvas.drawText("寸草金CUNJQjinsdaofihwafehofdmvpBGEOUWmevldnbuehwPOS:lXM", 0, baseY, mPaint);
Path path = new Path();
path.moveTo(0, 50);
path.lineTo(100, 200);
mCanvas.drawPath(path, mPaint);
mPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_OUT));
RectF rect = new RectF(0, 0, w, h);
mCanvas.drawRoundRect(rect, 50, 50, mPaint);
mPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN));
Matrix matrix = new Matrix();
matrix.setScale(w * 1f / mBitmap.getWidth(), w * 1f / mBitmap.getWidth());
mCanvas.drawBitmap(mBitmap, matrix, mPaint);
}
方案二:
private void init(Context context, AttributeSet attrs) {
mPaint = new Paint();
mPaint.setAntiAlias(true);
mPaint.setStrokeJoin(Paint.Join.ROUND);
mPaint.setStrokeCap(Paint.Cap.ROUND);
}
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.pic1);
mBmp = Bitmap.createBitmap(w, w, Bitmap.Config.ARGB_8888);
Canvas mCanvas = new Canvas(mBmp);
Matrix matrix = new Matrix();
float scale = w * 1f / getResources().getDisplayMetrics().widthPixels;
matrix.setScale(scale, scale);
mCanvas.drawBitmap(bitmap, matrix, mPaint);
mPaint.setShader(new BitmapShader(mBmp, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP));
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
setMeasuredDimension(widthMeasureSpec, widthMeasureSpec);
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
int r = getWidth() / 2;
canvas.drawCircle(r, r, r, mPaint);
}