自定义各种裁剪框、扫描框

由于项目的需要,我们需要三种裁剪框,矩形裁剪框相信大家都不陌生,矩形的比较简单,思路:例如:正方形的裁剪框,我们只需要设置画笔的颜色为半透明的,然后绘制上下左右四个矩形即可组成一个正方形,那么圆形的怎么画呢?如果是同样的思路,那么我们就需要画两个不规则的图形,来组成圆,关键的地方就是那个半圆弧怎么画?我想到了用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不是很理解的:这里有一篇文章写的超级赞:

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

自定义各种裁剪框、扫描框的相关文章

Zxing二维码精简(竖屏、拉伸处理、扫描框大小和扫描线移动)

本帖最后由 levil_ad 于 2013-12-30 13:55 编辑 最近没事做了下二维码扫描,用的是ZXing的开源代码,官方源码地址:http://code.google.com/p/zxing/downloads/list:我是在ZXing2.2基础上做的,因此只下载了ZXing-2.2.zip:此外还需要ZXing的核心Jar包,下载地址:http://repo1.maven.org/maven2/com/google/zxing/core/2.2/,只需下载core-2.2.jar

Android Zxing框架扫描解决扫描框大小,图片压缩问题

在我们是Zxing框架进行二维码扫描的时候,会发现,现在手机随着分辨率的增加,那个扫描框会越来越小,在1920*1280和1280*720还算比较正常,但是三星的几款手机note4,5,S6,等几款手机分辨率高达2560*1440,甚至一些手机高达3660的吧记不清了. 在这些手机扫描的时候,弹出的扫描Activity中间SurfaceView扫描窗口小的也是醉了, 不说了解决办法: 1:找到启动扫描的Intent    即: Intent openCameraIntent = new Inte

jQuery自定义漂亮的下拉框插件8种效果演示

原始的下拉框不好看这里推荐一个jQuery自定义漂亮的下拉框插件8种效果演示 在线预览 下载地址 实例代码 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 <!DOCTYPE html> <html lang="en" class=

Android 二维码扫描框 加四个角及中间横线自动下滑

红色为加四个角  黄色为扫描线自动下滑 /* * Copyright (C) 2008 ZXing authors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http:/

iOS 原生二维码扫描,带扫描框和扫描过程动画

在代码中使用了相对布局框架Masonry 准备两张图片,一张是扫描边框,一张是扫描时的细线分别命名 scanFrame.png和scanLine.png并提前放入工程 导入相对布局头文件 #define MAS_SHORTHAND #define MAS_SHORTHAND_GLOBALS #import "Masonry.h" 导入依赖头文件 #import <AVFoundation/AVFoundation.h> 具体代码如下: static const char *

CSS自定义select下拉选择框的样式(不用其他标签模拟)

CSS自定义select下拉选择框的样式(不用其他标签模拟):http://www.jb51.net/css/148841.html CSS美化选择框:http://www.cnblogs.com/shishm/archive/2012/03/02/2376759.html 1 <!DOCTYPE html> 2 <html> 3 <head lang="en"> 4 <meta charset="UTF-8"> 5

自定义SWT控件二之自定义多选下拉框

2.自定义下拉多选框 package com.view.control.select; import java.util.ArrayList; import java.util.HashMap; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import org.eclipse.swt.SWT; import org.eclipse.swt.custom.CLabel; import or

iOS:提示框(警告框)控件UIActionSheet的详解

提示框(警告框)控件2:UIActionSheet 功能:当点击按钮或标签等时,弹出一个提示框,显示必要的提示,然后通过添加的按钮完成需要的功能.它与导航栏类似,它继承自UIView. 风格类型: typedef NS_ENUM(NSInteger, UIActionSheetStyle) { UIActionSheetStyleAutomatic        = -1,       //iOS系统自动默认的风格 UIActionSheetStyleDefault          = UIB

iOS:提示框(警告框)控件UIAlertView的详解

提示框(警告框)控件:UIAlertView 功能:当点击按钮或标签等时,弹出一个提示框,显示必要的提示,然后通过添加的按钮完成需要的功能. 类型:typedef NS_ENUM(NSInteger, UIAlertViewStyle) { UIAlertViewStyleDefault = 0,                 //默认类型 UIAlertViewStyleSecureTextInput,          //安全密码的文本框输入类型 UIAlertViewStylePlai

[CSS]复选框单选框与文字对齐问题的研究与解决.

前言:今天碰到的这个问题, 恰好找到一个很好的博文, 在这里转载过来 学习下. 原文地址:复选框单选框与文字对齐问题的研究与解决. 目前中文网站上面的文字,就我的个人感觉而言,绝大多数网站的主流文字大小为12px,因为在目前高分辨率显示器屏幕下,11px的汉字,其像素点开始不规整,文字不如12px来的显示良好.12px大小的文字就是主流也是底线.然而12px的文字与单选框和复选框是不对齐的.例如下面这张雅虎中国首页在火狐浏览器下的截图: 雅虎中国首页单选框复选框与文字不对齐 这里,不是说,雅虎中