自定义二维码扫描界面 自定义

最近忙成代码狗,一直没时间更新博客,明天就是周末了,在下班前更新一篇近期写的代码。

因为产品需求,一开始调用系统相机,发现很多功能无法实现,只能自定义相机,自己之前自定义了相机,在Camera和Camera2的选择上犹豫了,因为iCamera容易上手,但是过时了,所以后来还是选择Camera2起步,痛苦挣扎了一周,终于实现了,后面会写一篇关于自定义相机的博客。

言归正传,今天分享的是做的一个自定义扫描界面,页面仿ZXing扫描页面,之前没做过,挣扎一下午,自定义了View,话不多说,上代码:


public class AutoScanView extends View {
    private Paint maskPaint;        //  蒙层的笔
    private Paint linePaint;        //  中间线的笔
    private Paint traAnglePaint;    //  边角的笔
    private Paint textPaint;        //  文字的笔

    private final int maskColor = Color.parseColor("#60000000");                          //蒙在摄像头上面区域的半透明颜色
    private final int triAngleColor = Color.parseColor("#76EE00");                        //边角的颜色
    private final int lineColor = Color.parseColor("#FF0000");                            //中间线的颜色
    private final int textColor = Color.parseColor("#CCCCCC");                            //文字的颜色
    private final int triAngleLength = dp2px(20);                                         //每个角的点距离
    private final int triAngleWidth = dp2px(4);                                           //每个角的点宽度
    private final int textMarinTop = dp2px(36);                                           //文字距离识别框的距离
    private int lineOffsetCount = 0;
    private static final int MIN_FRAME_WIDTH = 240;
    private static final int MAX_FRAME_WIDTH = 1200; // = 5/8 * 1920

    public AutoScanPlateView(Context context) {
        this(context, null);
    }

    public AutoScanPlateView(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public AutoScanPlateView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        maskPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
        maskPaint.setColor(maskColor);

        traAnglePaint = new Paint(Paint.ANTI_ALIAS_FLAG);
        traAnglePaint.setColor(triAngleColor);
        traAnglePaint.setStrokeWidth(triAngleWidth);
        traAnglePaint.setStyle(Paint.Style.STROKE);

        linePaint = new Paint(Paint.ANTI_ALIAS_FLAG);
        linePaint.setColor(lineColor);

        textPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
        textPaint.setColor(textColor);
        textPaint.setTextSize(dp2px(18));
    }

    @Override
    protected void onDraw(Canvas canvas) {
        DisplayMetrics dm = getResources().getDisplayMetrics();

        int widthPixels = dm.widthPixels;// 屏幕宽
        int heightPixels = dm.heightPixels;// 屏幕高
        int midWidth = widthPixels / 2;
        int midHeight = heightPixels / 2;
        int scanWidth = getScanWidth(widthPixels, MIN_FRAME_WIDTH, MAX_FRAME_WIDTH);//  矩形宽
        int scanHeight = scanWidth / 2; //  矩形高

        Point midPoint = new Point(midWidth,midHeight); //  中心点
        int leftOffset = midPoint.x -( scanWidth / 2);
        int topOffset = midPoint.y - (scanHeight / 2);
        Rect frame = new Rect(leftOffset, topOffset, leftOffset + scanWidth, topOffset + scanHeight);

        int width = canvas.getWidth();
        int height = canvas.getHeight();

        // 除了中间的识别区域,其他区域都将蒙上一层半透明的图层
        canvas.drawRect(0, 0, width, frame.top, maskPaint);
        canvas.drawRect(0, frame.top, frame.left, frame.bottom + 1, maskPaint);
        canvas.drawRect(frame.right + 1, frame.top, width, frame.bottom + 1, maskPaint);
        canvas.drawRect(0, frame.bottom + 1, width, height, maskPaint);

        String text = "将内容放入框内,即可自动扫描";
        canvas.drawText(text, (width - textPaint.measureText(text)) / 2, frame.bottom + textMarinTop, textPaint);

        // 四个角落的三角
        Path leftTopPath = new Path();
        leftTopPath.moveTo(frame.left + triAngleLength, frame.top + triAngleWidth / 2);
        leftTopPath.lineTo(frame.left + triAngleWidth / 2, frame.top + triAngleWidth / 2);
        leftTopPath.lineTo(frame.left + triAngleWidth / 2, frame.top + triAngleLength);
        canvas.drawPath(leftTopPath, traAnglePaint);

        Path rightTopPath = new Path();
        rightTopPath.moveTo(frame.right - triAngleLength, frame.top + triAngleWidth / 2);
        rightTopPath.lineTo(frame.right - triAngleWidth / 2, frame.top + triAngleWidth / 2);
        rightTopPath.lineTo(frame.right - triAngleWidth / 2, frame.top + triAngleLength);
        canvas.drawPath(rightTopPath, traAnglePaint);

        Path leftBottomPath = new Path();
        leftBottomPath.moveTo(frame.left + triAngleWidth / 2, frame.bottom - triAngleLength);
        leftBottomPath.lineTo(frame.left + triAngleWidth / 2, frame.bottom - triAngleWidth / 2);
        leftBottomPath.lineTo(frame.left + triAngleLength, frame.bottom - triAngleWidth / 2);
        canvas.drawPath(leftBottomPath, traAnglePaint);

        Path rightBottomPath = new Path();
        rightBottomPath.moveTo(frame.right - triAngleLength, frame.bottom - triAngleWidth / 2);
        rightBottomPath.lineTo(frame.right - triAngleWidth / 2, frame.bottom - triAngleWidth / 2);
        rightBottomPath.lineTo(frame.right - triAngleWidth / 2, frame.bottom - triAngleLength);
        canvas.drawPath(rightBottomPath, traAnglePaint);

        //循环划线,从上到下
        if (lineOffsetCount > frame.bottom - frame.top - dp2px(10)) {
            lineOffsetCount = 0;
        } else {
            lineOffsetCount = lineOffsetCount + 2;
//            canvas.drawLine(frame.left, frame.top + lineOffsetCount, frame.right, frame.top + lineOffsetCount, linePaint);    //画一条红色的线
            Rect lineRect = new Rect();
            lineRect.left = frame.left;
            lineRect.top = frame.top + lineOffsetCount;
            lineRect.right = frame.right;
            lineRect.bottom = frame.top + dp2px(10) + lineOffsetCount;
            canvas.drawBitmap(((BitmapDrawable)(getResources().getDrawable(R.mipmap.scanline))).getBitmap(), null, lineRect, linePaint);
        }
        postInvalidateDelayed(10L, frame.left, frame.top, frame.right, frame.bottom);
    }

    private int getScanWidth(int screemWidth, int min, int max) {
        int dim = 5 * screemWidth / 8;  //  屏幕宽的5/8
        if (dim < min) {
            dim = min;
        }
        if (dim > max) {
            dim = max;
        }
        return dim;
    }

    private int dp2px(int dp) {
        float density = getContext().getResources().getDisplayMetrics().density;
        return (int) (dp * density + 0.5f);
    }
}

这里面很多元素可以自行更改,因为业务需求,我是把扫描框高度减半,大小可自行更改,屏占比参考了ZXing的计算方式。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值