android 二维码扫描(zxing使用小结)

本文详细介绍了如何优化二维码扫描应用的界面展示效果,包括调整扫描框位置以适应不同屏幕布局,解决扫描框内图片变形问题,并优化了界面绘制流程。通过设置全屏模式来消除扫描框与二维码之间的视觉偏差,同时通过CameraManager.java中的getFramingRect()方法灵活调整扫描框大小和位置。此外,通过CameraConfigurationManager.java中的setDesiredCameraParameters方法确保预览图片正确显示,避免图片失真。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

主要有三点:

1、界面绘制,包括4个边角、上下滚动的横线、在画布上添加文字

2、调整二维码扫描框的位置。

3、解决图片被压变形的问题。

 

1、界面绘制

ViewfinderView.java中onDraw()方法

@Override
    public void onDraw(Canvas canvas) {
        // 中间的扫描框,你要修改扫描框的大小,去CameraManager里面修改
        Rect frame = CameraManager.get().getFramingRect();
        int top = frame.top;
        int left = frame.left;
        int right = frame.right;
        int bottom = frame.bottom;
        frame = new Rect(left , top, right , bottom );
        // 初始化中间线滑动的最上边和最下边
        if (!isFirst) {
            isFirst = true;
            slideTop = frame.top;
            slideBottom = frame.bottom;
        }
 
        // 获取屏幕的宽和高
        int width = canvas.getWidth();
        int height = canvas.getHeight();
 
        // 画出扫描框外面的阴影部分,共四个部分,扫描框的上面到屏幕上面,扫描框的下面到屏幕下面
        // 扫描框的左边面到屏幕左边,扫描框的右边到屏幕右边
        // Draw the exterior (i.e. outside the framing rect) darkened
        paint.setColor(resultBitmap != null ? resultColor : maskColor);
        canvas.drawRect(0, 0, width, frame.top, paint);
        canvas.drawRect(0, frame.top, frame.left, frame.bottom + 1, paint);
        canvas.drawRect(frame.right + 1, frame.top, width, frame.bottom + 1,
                paint);
        canvas.drawRect(0, frame.bottom + 1, width, height, paint);
 
        if (resultBitmap != null) {
            // Draw the opaque result bitmap over the scanning rectangle
            paint.setAlpha(OPAQUE);
            canvas.drawBitmap(resultBitmap, frame.left, frame.top, paint);
        } else {
            // 画扫描框边上的角,总共8个部分
            paint.setColor(Color.GREEN);
            canvas.drawRect(frame.left, frame.top, frame.left + ScreenRate,
                    frame.top + CORNER_WIDTH, paint);
            canvas.drawRect(frame.left, frame.top, frame.left + CORNER_WIDTH, frame.top
                    + ScreenRate, paint);
            canvas.drawRect(frame.right - ScreenRate, frame.top, frame.right,
                    frame.top + CORNER_WIDTH, paint);
            canvas.drawRect(frame.right - CORNER_WIDTH, frame.top, frame.right, frame.top
                    + ScreenRate, paint);
            canvas.drawRect(frame.left, frame.bottom - CORNER_WIDTH, frame.left
                    + ScreenRate, frame.bottom, paint);
            canvas.drawRect(frame.left, frame.bottom - ScreenRate,
                    frame.left + CORNER_WIDTH, frame.bottom, paint);
            canvas.drawRect(frame.right - ScreenRate, frame.bottom - CORNER_WIDTH,
                    frame.right, frame.bottom, paint);
            canvas.drawRect(frame.right - CORNER_WIDTH, frame.bottom - ScreenRate,
                    frame.right, frame.bottom, paint);
             
            //绘制中间的线,每次刷新界面,中间的线往下移动SPEEN_DISTANCE
             
            slideTop += SPEEN_DISTANCE;
            if(slideTop >= frame.bottom){
                slideTop = frame.top;
            }
            Rect lineRect = new Rect(); 
            lineRect.left = frame.left; 
            lineRect.right = frame.right; 
            lineRect.top = slideTop; 
            lineRect.bottom = slideTop + 18
            canvas.drawBitmap(((BitmapDrawable)(getResources().getDrawable(R.drawable.qrcode_scan_line))).getBitmap(), null, lineRect, paint);
             
            //画扫描框下面的字
//            paint.setColor(Color.WHITE);   
//            paint.setTextSize(TEXT_SIZE * density);   
//            paint.setAlpha(0x40);   
//            paint.setTypeface(Typeface.create(System, Typeface.BOLD));  
//            String text = 将二维码放入框内, 即可自动扫描; 
//            float textWidth = paint.measureText(text); 
//             
//            canvas.drawText(text, (width - textWidth)/2, (float) (frame.bottom + (float)TEXT_PADDING_TOP *density), paint);
             
             
 
            Collection<resultpoint> currentPossible = possibleResultPoints;
            Collection<resultpoint> currentLast = lastPossibleResultPoints;
            if (currentPossible.isEmpty()) {
                lastPossibleResultPoints = null;
            } else {
                possibleResultPoints = new HashSet<resultpoint>(5);
                lastPossibleResultPoints = currentPossible;
                paint.setAlpha(OPAQUE);
                paint.setColor(resultPointColor);
                for (ResultPoint point : currentPossible) {
                    canvas.drawCircle(frame.left + point.getX(), frame.top
                            + point.getY(), 6.0f, paint);
                }
            }
            if (currentLast != null) {
                paint.setAlpha(OPAQUE / 2);
                paint.setColor(resultPointColor);
                for (ResultPoint point : currentLast) {
                    canvas.drawCircle(frame.left + point.getX(), frame.top
                            + point.getY(), 3.0f, paint);
                }
            }
 
             
            //只刷新扫描框的内容,其他地方不刷新
            postInvalidateDelayed(ANIMATION_DELAY, frame.left, frame.top,
                    frame.right, frame.bottom);
             
        }
    }</resultpoint></resultpoint></resultpoint>

2、调整位置

如果不设置全屏,扫描框的位置和取图的位置高度目测会有50px误差, 不全屏公式:((Y - 标题栏 - 状态栏)/2 - 扫描框高度)/2 = y轴坐标 只要不全屏:就会有误差,导致框中的二维码靠上或者远离二维码才会扫描成功 如果设置为全屏,就不会有误差,请了解内情的大神告知笔者,想知道什么原因造成 CameraManager.java 中 getFramingRect()方法


public Rect getFramingRect() {
    Point screenResolution = configManager.getScreenResolution();
    if (framingRect == null) {
      if (camera == null) {
        return null;
      }
      /* 确定在固定比例分辨率下二维码扫描框的宽高*/ 
      int width = screenResolution.x * 3 / 4;
      if (width < MIN_FRAME_WIDTH) {
        width = MIN_FRAME_WIDTH;
      } else if (width > MAX_FRAME_WIDTH) {
        width = MAX_FRAME_WIDTH;
      }
      int height = screenResolution.y * 3 / 4;
      if (height < MIN_FRAME_HEIGHT) {
        height = MIN_FRAME_HEIGHT;
      } else if (height > MAX_FRAME_HEIGHT) {
        height = MAX_FRAME_HEIGHT;
      }
      //计算x轴y轴坐标,可在此调整二维码框的位置
      int leftOffset = (screenResolution.x - width) / 2 ;
      int topOffset = ((screenResolution.y) /2 - height) / 2 ;
      framingRect = new Rect(leftOffset, topOffset, leftOffset + width, topOffset + height);
      Log.d(TAG, Calculated framing rect:  + framingRect);
    }
    return framingRect;
  }

3、框中图片变形

CameraConfigurationManager.java中void setDesiredCameraParameters(Camera camera)方法

/**
     * Sets the camera up to take preview images which are used for both preview
     * and decoding. We detect the preview format here so that
     * buildLuminanceSource() can build an appropriate LuminanceSource subclass.
     * In the future we may want to force YUV420SP as it's the smallest, and the
     * planar Y can be used for barcode scanning without a copy in some cases.
     */
    void setDesiredCameraParameters(Camera camera) {
        // Camera.Parameters parameters = camera.getParameters();
        // Log.d(TAG, Setting preview size:  + cameraResolution);
        // parameters.setPreviewSize(cameraResolution.x, cameraResolution.y);
        // setFlash(parameters);
        // setZoom(parameters);
        // //setSharpness(parameters);
        // //modify here
        // camera.setDisplayOrientation(90);
        // camera.setParameters(parameters);
        Camera.Parameters parameters = camera.getParameters();
        List<size> supportedPreviewSizes = parameters
                .getSupportedPreviewSizes();
        int position = 0;
        if (supportedPreviewSizes.size() > 2) {
            position = supportedPreviewSizes.size() / 2 + 1;// supportedPreviewSizes.get();
        } else {
            position = supportedPreviewSizes.size() / 2;
        }
 
        int width = supportedPreviewSizes.get(position).width;
        int height = supportedPreviewSizes.get(position).height;
        Log.d(TAG, Setting preview size:  + cameraResolution);
        camera.setDisplayOrientation(90);
        cameraResolution.x = width;
        cameraResolution.y = height;
        parameters.setPreviewSize(width, height);
        setFlash(parameters);
        setZoom(parameters);
        // setSharpness(parameters);
        camera.setParameters(parameters);
    }</size>

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值