原理:

  1. 创建一个空白的bitmap。
  2. 通过bitmap创建Canvas。
  3. 在Canvas中绘制出path。
  4. 设置画笔Xfermode为PorterDuff.Mode.SRC_IN。
  5. 在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原理:

android 剪切图片图片_渐变色

android 剪切图片图片_android 剪切图片图片_02

附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 圆

例如:

android 剪切图片图片_实线_03

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);

效果:

android 剪切图片图片_android 剪切图片图片_04

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:

android 剪切图片图片_android 剪切图片图片_05

true:

android 剪切图片图片_渐变色_06

画三角形
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;   
    }
画曲线(贝塞尔)

android 剪切图片图片_实线_07

//画笔设置空心是曲线,设置实心是……..
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:想要居中区域的高度

android 剪切图片图片_实线_08

Paint.FontMetrics fontMetrics=paint.getFontMetrics();
        fontMetrics.top
        fontMetrics.ascent
        fontMetrics.descent
        fontMetrics.bottom

android 剪切图片图片_实线_09

文字的高度为bottom - top