由于项目的需要,我们需要三种裁剪框,矩形裁剪框相信大家都不陌生,矩形的比较简单,思路:例如:正方形的裁剪框,我们只需要设置画笔的颜色为半透明的,然后绘制上下左右四个矩形即可组成一个正方形,那么圆形的怎么画呢?如果是同样的思路,那么我们就需要画两个不规则的图形,来组成圆,关键的地方就是那个半圆弧怎么画?我想到了用path,下面大家看一下效果:
正方形:
圆形:
带角标的矩形:
下面看实现代码:
/**
* 绘制裁剪框
*
* @param canvas
*/
private void drawShape(Canvas canvas) {
//矩形的画笔
Paint paint = new Paint();
paint.setStyle(Paint.Style.FILL);
paint.setColor(getResources().getColor(R.color.capture_view_bg));
paint.setAntiAlias(true);
//裁剪框白线的画笔
Paint lPaint = new Paint();
lPaint.setStyle(Paint.Style.FILL);
lPaint.setColor(Color.WHITE);
lPaint.setStrokeWidth(1);
lPaint.setAntiAlias(true);
//裁剪框角标的画笔
Paint llPaint=new Paint();
llPaint.setStyle(Paint.Style.FILL);
llPaint.setColor(Color.WHITE);
llPaint.setStrokeWidth(5);
llPaint.setAntiAlias(true);
//画圆的画笔
Paint rPaint= new Paint();
rPaint.setStyle(Paint.Style.STROKE);
rPaint.setColor(Color.WHITE);
rPaint.setStrokeWidth(5);
rPaint.setAntiAlias(true);
switch (shape) {
case Rect:
eage = width * 4 / 5;//设定裁剪框的变成是屏幕宽度的五分之四
top = (height - eage) / 2;//绘制的正方形的顶部距离view顶端的距离
bottom = eage + top;//绘制的正方形的底部距离view顶端的距离
canvas.drawRect(0, 0, width, top, paint);//上矩形
canvas.drawRect(0, top, width / 10, bottom, paint);//左矩形
canvas.drawRect(width * 9 / 10, top, width, bottom, paint);//右矩形
canvas.drawRect(0, bottom, width, height, paint);//下矩形
canvas.drawLine(width / 10, top, width * 9 / 10, top, lPaint);//上白线
canvas.drawLine(width / 10, top, width / 10, bottom, lPaint);//左白线
canvas.drawLine(width * 9 / 10, top, width * 9 / 10, bottom, lPaint);//右白线
canvas.drawLine(width / 10, bottom, width * 9 / 10, bottom, lPaint);//下白线
break;
case Circle:
eage = width * 4 / 5;//设定裁剪框的变成是屏幕宽度的五分之四
top = (height - eage) / 2;//绘制的正方形的顶部距离view顶端的距离
bottom = eage + top;//绘制的正方形的底部距离view顶端的距离
Path LPath=new Path();
LPath.lineTo(width / 2, 0);
LPath.lineTo(width / 2, top);
LPath.cubicTo(-width / 30, top, -width / 30, bottom, width / 2, bottom);//三阶贝塞尔曲线
LPath.lineTo(width / 2, height);
LPath.lineTo(0, height);
LPath.close();
Path RPath=new Path();
RPath.moveTo(width,0);
RPath.lineTo(width / 2, 0);
RPath.lineTo(width / 2, top);
RPath.cubicTo(width * 31 / 30, top, width * 31 / 30, bottom, width / 2, bottom);
RPath.lineTo(width / 2, height);
RPath.lineTo(width, height);
RPath.close();
canvas.drawPath(LPath, paint);
canvas.drawPath(RPath,paint);
canvas.drawCircle(width/2,height/2,eage/2+2,rPaint);
break;
case ScreenRect:
rectTop = (height - width / 2) / 2;//裁剪矩形上边缘距离view上方的距离
rectBottom=rectTop + width / 2;//裁剪矩形底部边缘距离上方的距离
rectCorner=width/16;
//画矩形
canvas.drawRect(0, 0, width, rectTop, paint);//上矩形
canvas.drawRect(0, rectBottom, width, height, paint);//下矩形
//画线
canvas.drawLine(0,rectTop,width,rectTop,lPaint);//上边线
canvas.drawLine(0,rectTop,0,rectBottom,lPaint);//左边线
canvas.drawLine(width,rectTop,width,rectBottom,lPaint);//右边线
canvas.drawLine(0,rectBottom,width,rectBottom,lPaint);//下边线
//画8个小角标
canvas.drawLine(0,rectTop+1,rectCorner,rectTop+1,llPaint);//左上横角标
canvas.drawLine(1,rectTop,1,rectTop+rectCorner,llPaint);//左上竖角标
canvas.drawLine(width-rectCorner,rectTop+1,width,rectTop+1,llPaint);//右上横角标
canvas.drawLine(width-1,rectTop,width-1,rectCorner+rectTop,llPaint);//右上竖角标
canvas.drawLine(0,rectBottom-1,rectCorner,rectBottom-1,llPaint);//左下横角标
canvas.drawLine(1,rectBottom,1,rectBottom-rectCorner,llPaint);//左下竖角标
canvas.drawLine(width,rectBottom-1,width-rectCorner,rectBottom-1,llPaint);//右下横角标
canvas.drawLine(width-1,rectBottom,width-1,rectBottom-rectCorner,llPaint);//右下竖角标
break;
default:
break;
}
}
如果对path不是很理解的:这里有一篇文章写的超级赞:
代码我都做了比较详细的注释,相信比较好理解,不懂的可以留言哦!
其实裁剪框,弄好了,就剩下裁剪了呗,裁剪比较简单,这里我是采用手机屏幕截图的方式实现的只贴代码,有兴趣的童鞋可以看一下,其实这个截图方式不是很满意,有好的方式的欢迎大家讨论:
首先一个工具类:
**
* 获得屏幕相关的辅助类
*/
public class ScreenUtils {
private ScreenUtils() {
/* cannot be instantiated */
throw new UnsupportedOperationException("cannot be instantiated");
}
/**
* 获得屏幕宽度
*
* @param context
* @return
*/
public static int getScreenWidth(Context context) {
WindowManager wm = (WindowManager) context
.getSystemService(Context.WINDOW_SERVICE);
DisplayMetrics outMetrics = new DisplayMetrics();
wm.getDefaultDisplay().getMetrics(outMetrics);
return outMetrics.widthPixels;
}
/**
* 获得屏幕高度
*
* @param context
* @return
*/
public static int getScreenHeight(Context context) {
WindowManager wm = (WindowManager) context
.getSystemService(Context.WINDOW_SERVICE);
DisplayMetrics outMetrics = new DisplayMetrics();
wm.getDefaultDisplay().getMetrics(outMetrics);
return outMetrics.heightPixels;
}
/**
* 获得状态栏的高度
*
* @param context
* @return
*/
public static int getStatusHeight(Context context) {
int statusHeight = -1;
try {
Class<?> clazz = Class.forName("com.android.internal.R$dimen");
Object object = clazz.newInstance();
int height = Integer.parseInt(clazz.getField("status_bar_height")
.get(object).toString());
statusHeight = context.getResources().getDimensionPixelSize(height);
} catch (Exception e) {
e.printStackTrace();
}
return statusHeight;
}
/**
* 获取当前屏幕截图,包含状态栏
*
* @param activity
* @return
*/
public static Bitmap snapShotWithStatusBar(Activity activity) {
View view = activity.getWindow().getDecorView();
view.setDrawingCacheEnabled(true);
view.buildDrawingCache();
Bitmap bmp = view.getDrawingCache();
int width = getScreenWidth(activity);
int height = getScreenHeight(activity);
Bitmap bp = null;
bp = Bitmap.createBitmap(bmp, 0, 0, width, height);
view.destroyDrawingCache();
return bp;
}
/**
* 获取当前屏幕截图,不包含状态栏
*
* @param activity
* @return
*/
public static Bitmap snapShotWithoutStatusBar(Activity activity) {
View view = activity.getWindow().getDecorView();
view.setDrawingCacheEnabled(true);
view.buildDrawingCache();
Bitmap bmp = view.getDrawingCache();
Rect frame = new Rect();
activity.getWindow().getDecorView().getWindowVisibleDisplayFrame(frame);
int statusBarHeight = frame.top;
int width = getScreenWidth(activity);
int height = getScreenHeight(activity);
Bitmap bp = null;
bp = Bitmap.createBitmap(bmp, 0, statusBarHeight, width, height
- statusBarHeight);
view.destroyDrawingCache();
return bp;
}
}
下面的具体的实现:使用到Bitmap的creatBitmap:
/**
* 获取裁剪图片
*
* @param activity
* @return
*/
public static Bitmap takeScreenShot(Activity activity) {
//去掉标题栏,actionbar 的高度
Bitmap b = Bitmap.createBitmap(ScreenUtils.snapShotWithStatusBar(activity), 0,
ScreenUtils.getScreenHeight(activity) - height-viewHeight, width,
height);
switch (CaptureView.shape) {
case Rect:
//偏移一个像素,避免截取白线
b = Bitmap.createBitmap(b, width / 10 + 1, top + 1, eage - 2, eage - 2);
break;
case Circle:
//偏移一个像素,避免截取白线
// b = toRoundBitmap(Bitmap.createBitmap(b, width / 10 + 1, top + 1, eage - 2, eage - 2));
//偏移一个像素,避免截取白线
b = Bitmap.createBitmap(b, width / 10 + 1, top + 1, eage - 2, eage - 2);
break;
case ScreenRect:
//偏移一个像素,避免截取白线
b = Bitmap.createBitmap(b, 6, rectTop+6, width-12, width/2 - 12);
break;
default:
break;
}
return comp(b);
}
关于压缩图片的方式这个比较简单,从网站找了一段代码:
public static Bitmap comp(Bitmap image) {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
image.compress(Bitmap.CompressFormat.JPEG, 100, baos);
if (baos.toByteArray().length / 1024 > 1024) {//判断如果图片大于1M,进行压缩避免在生成图片(BitmapFactory.decodeStream)时溢出
baos.reset();//重置baos即清空baos
image.compress(Bitmap.CompressFormat.JPEG, 50, baos);//这里压缩50%,把压缩后的数据存放到baos中
}
ByteArrayInputStream isBm = new ByteArrayInputStream(baos.toByteArray());
BitmapFactory.Options newOpts = new BitmapFactory.Options();
//开始读入图片,此时把options.inJustDecodeBounds 设回true了
newOpts.inJustDecodeBounds = true;
Bitmap bitmap = BitmapFactory.decodeStream(isBm, null, newOpts);
newOpts.inJustDecodeBounds = false;
int w = newOpts.outWidth;
int h = newOpts.outHeight;
//现在主流手机比较多是800*480分辨率,所以高和宽我们设置为
float hh = 800f;//这里设置高度为800f
float ww = 480f;//这里设置宽度为480f
//缩放比。由于是固定比例缩放,只用高或者宽其中一个数据进行计算即可
int be = 1;//be=1表示不缩放
if (w > h && w > ww) {//如果宽度大的话根据宽度固定大小缩放
be = (int) (newOpts.outWidth / ww);
} else if (w < h && h > hh) {//如果高度高的话根据宽度固定大小缩放
be = (int) (newOpts.outHeight / hh);
}
if (be <= 0)
be = 1;
newOpts.inSampleSize = be;//设置缩放比例
//重新读入图片,注意此时已经把options.inJustDecodeBounds 设回false了
isBm = new ByteArrayInputStream(baos.toByteArray());
bitmap = BitmapFactory.decodeStream(isBm, null, newOpts);
return compressImage(bitmap);//压缩好比例大小后再进行质量压缩
}
private static Bitmap compressImage(Bitmap image) {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
image.compress(Bitmap.CompressFormat.JPEG, 100, baos);//质量压缩方法,这里100表示不压缩,把压缩后的数据存放到baos中
int options = 100;
while (baos.toByteArray().length / 1024 > 100) { //循环判断如果压缩后图片是否大于100kb,大于继续压缩
baos.reset();//重置baos即清空baos
image.compress(Bitmap.CompressFormat.JPEG, options, baos);//这里压缩options%,把压缩后的数据存放到baos中
options -= 10;//每次都减少10
}
ByteArrayInputStream isBm = new ByteArrayInputStream(baos.toByteArray());//把压缩后的数据baos存放到ByteArrayInputStream中
Bitmap bitmap = BitmapFactory.decodeStream(isBm, null, null);//把ByteArrayInputStream数据生成图片
return bitmap;
}
就这样吧。~
版权声明:本文为博主原创文章,未经博主允许不得转载。
时间: 2024-10-04 13:55:43