原理:
- 创建一个空白的bitmap。
- 通过bitmap创建Canvas。
- 在Canvas中绘制出path。
- 设置画笔Xfermode为PorterDuff.Mode.SRC_IN。
- 在Canvas中把需要裁剪的图片绘制出来即可。
代码:
Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
paint.setStyle(Paint.Style.FILL);
//创建空白bitmap
Bitmap temp = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(temp);
//获取路径
Path path = xx.getPath();
//绘制路径
bitmapCanvas.drawPath(path, paint);
//设置画笔属性
paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN));
//bitmap自身绘制区域
Rect src = new Rect(0, 0, newBitmap.getWidth(), newBitmap.getHeight());
//bitmap画到画布区域
Rect dst = new Rect(0, 0, temp.getWidth(), temp.getHeight());
canvas.drawBitmap(newBitmap, src , dst, paint);
//该temp为裁剪后的图形
return temp;
附PorterDuff.Mode原理:
附2 画笔及画布:
Paint 画笔
setStrokeWidth
设置画笔宽度
setShader
设置材质,例如渐变色:
Shader mShader = new LinearGradient(
0,0,100,100,
new int[]{Color.RED,Color.GREEN,Color.BLUE,Color.YELLOW},
null,
Shader.TileMode.REPEAT);
setShadowLayer(10, 15, 15, Color.GREEN)
设置阴影,阴影为绿色
setPathEffect
画路径特效,PathEffect一共有五个子类:ComposePathEffect, CornerPathEffect, DashPathEffect, DiscretePathEffect, PathDashPathEffect, SumPathEffect, 其中的DashPathEffect就是我们需要的虚线效果。
例如 虚线:new DashPathEffect(new float[] {10, 5}, 0)
虚线的一个单位就是10像素的实线加上5像素的空白,然后以它为单位去不断重复画,从而形成一条虚线。而如果设定的参数是new float[] {10, 5,20, 10},那么虚线的一个单位就是由10像素实线,5像素空白,20像素实线,10像素空白组成的虚线段。
另一个参数代表偏移,一般我们设置为0即可,如果要实现虚线的动画效果的话,可以不断改变这个值,从而让虚线动起来。
setStrokeCap
设置笔刷的样式
Paint.Cap.ROUND 圆
例如:
setShader
设置着色器
例如设置渐变色:
int[] SECTION_COLORS = { Color.GREEN, Color.RED };
int maxCount = 100;
int currentCount = 78;
mPaint = new Paint();
mPaint.setAntiAlias(true);
mPaint.setStyle(Paint.Style.STROKE);
mPaint.setStrokeWidth(storkeWidth);
mPaint.setColor(Color.BLACK);
int storkeWidth = 40;
int storkeSelfWidth = 20;
int angleProgress = currentCount * 360 / maxCount;
//参数1:渐变色起始x坐标,
//参数2:渐变色起始y坐标,
//参数3:渐变色结束x坐标,
//参数4:渐变色结束y坐标,
//参数5:渐变色颜色数组
LinearGradient shader = new LinearGradient(mWidth / 2, 0, mWidth / 2, mHeight, SECTION_COLORS, null,
Shader.TileMode.MIRROR);
mPaint.setShader(shader);
RectF rectBlackBg = new RectF(storkeSelfWidth, storkeSelfWidth, mWidth - storkeSelfWidth, mHeight - storkeSelfWidth);
canvas.drawArc(rectBlackBg, 270 - angleProgress, angleProgress, false, mPaint);
效果:
Canvas 画布
画点
canvas.drawPoint(60, 400, p); //画一个点
canvas.drawPoints(new float[]{60,400, 65,400, 70,400}, p); //画多个点
画圆
// 在(40,50)位置,以此为中心画半径为30的圆,由paint的style属性判断是否空心
canvas.drawCircle(40, 50, 30, paint);
画线
canvas.drawLine(60, 40, 100, 40, p);// 画线
float[] pts={10,10,100,100, 200,200,400,400};
canvas.drawLines(pts, paint); //画多条线
画矩形
//10左 170上 70右 200下
canvas.drawRect(10, 170, 70, 200, paint);
画圆角矩形
RectF oval3 = new RectF(80, 260, 200, 300);
canvas.drawRoundRect(oval3, 20, 20, p); //第二个参数是x半径,第三个参数是y半径
画椭圆形
//左 上 右 下
RectF re=new RectF(10,220,70,250);
canvas.drawOval(re, paint);
画圆弧
//设置圆环的宽度
paint.setStrokeWidth(roundProgressWidth);
//设置进度的颜色
paint.setColor(roundProgressColor);
//用于定义的圆弧的形状和大小的界限 0,0 左上角 100, 100 右下角
RectF oval = new RectF(0, 0, 100, 100);
//设置空心
paint.setStyle(Paint.Style.STROKE);
//消除锯齿
paint.setAntiAlias(true);
//根据进度画圆弧
//-90 表示从顶部开始
//50表示多少度,最大360
//false 表示空心 true表示圆弧两边有往中心的连接线
canvas.drawArc(oval, -90, 50, false, paint);
false:
true:
画三角形
Path path=new Path();
path.moveTo(10, 330);
path.lineTo(70,330);
path.lineTo(40,270);
path.close();
canvas.drawPath(path, paint);
画梯形
Path path1=new Path();
path1.moveTo(10, 410);
path1.lineTo(70,410);
path1.lineTo(55,350);
path1.lineTo(25, 350);
path1.close();
canvas.drawPath(path1, paint);
画扇形
RectF re=new RectF(0,0,50,50);
canvas.drawArc(re, 0, 60, true, mPaint); //0:角度开始 60:保留多少度
画图片
canvas.drawBitmap(bitmap, 250,360, p);
合并两个图片
private Bitmap toConformBitmap(Bitmap background, Bitmap foreground) {
int bgWidth = background.getWidth();
int bgHeight = background.getHeight();
//创建一个新的位图
Bitmap newbmp = Bitmap.createBitmap(bgWidth, bgHeight, Config.ARGB_8888);
Canvas cv = new Canvas(newbmp);
cv.drawBitmap(background, 0, 0, null);
cv.drawBitmap(foreground, 0, 0, null);
//保存
cv.save(Canvas.ALL_SAVE_FLAG);
//存储
cv.restore();
return newbmp;
}
画曲线(贝塞尔)
//画笔设置空心是曲线,设置实心是……..
mPaint.setStyle(Paint.Style.STROKE);
Path path = new Path();
path.moveTo( Po.x , Po.y );
path.quadTo( P1.x , P1.y , P2.x , P2.y );
canvas.drawPath(path,mPaint);
画文本
canvas.drawText(text, x, 文本bottom, mPaint)
如果paint.setTextAlign(Paint.Align.CENTER);
canvas.drawText(text, 区域中间x, 区域中间y, mPaint)
注意!,文本上下不居中,默认靠下,需要修改为:
Paint.FontMetrics fontMetrics = textPaint.getFontMetrics();
//计算文字高度
float fontHeight = fontMetrics.bottom -fontMetrics.top;
//计算文字baseline
float textBaseY = h - (h - fontHeight) / 2 - fontMetrics.bottom;
//文字描绘的位置
canvas.drawText(text, (float) (width * 0.5), textBaseY, textPaint);
h:想要居中区域的高度
Paint.FontMetrics fontMetrics=paint.getFontMetrics();
fontMetrics.top
fontMetrics.ascent
fontMetrics.descent
fontMetrics.bottom
文字的高度为bottom - top