学习Zxing的心得

   今天研究了一下Zxing的用法,感谢广大网友的技术分享!~


  ZXing是一个开放源码的,用Java实现的多种格式的1D/2D条码图像处理库,它包含了联系到其他语言的端口。Zxing可以实现使用手机的内置的摄像头完成条形码的扫描及解码。该项目可实现的条形码编码和解码。总得来说就一句话,这玩意是google老大给出来的,用来生成二维码和条形码的


我找了很久前前后后下载了十几个demo都没什么让我满意的,要不就是没有生成条形码的,要不就是没有自定义扫描样式的。下面分享一个网友制作的demo:下载地址:http://download.csdn.net/detail/liaoinstan/9258087,感谢分享!~

  

可以选择手机本地图片进行扫描

       

  这个demo包含了动态扫描线以及,生成二维码与条形码,

       生成二维码演示

        

      //该demo存在一些小问题

       在原demo生成的二维码当生成的文字为中文时,用微信扫描会出现乱码问题

        我的修改方法是在MainActivity 对二维码生成按钮点击事件中做了修改

原来是:
case R.id.btn_create_qr:
 {
 String contentString = edit_qr.getText().toString();
 if (!contentString.equals("")) {
 //根据字符串生成二维码图片并显示在界面上,第二个参数为图片的大小(350*350)
 Bitmap qrCodeBitmap = EncodingHandler.createQRCode(contentString, 350);
 
 if(qrCodeBitmap!=null) mImageView.setImageBitmap(qrCodeBitmap);
 else Toast.makeText(this, "解析错误", Toast.LENGTH_SHORT).show();
 }else {
 Toast.makeText(this, "Text can not be empty", Toast.LENGTH_SHORT).show();
 }
 break;
 }
修改后
case R.id.btn_create_qr:
 {
 String contentString = edit_qr.getText().toString();
 if (!contentString.equals("")) {
 //根据字符串生成二维码图片并显示在界面上,第二个参数为图片的大小(350*350)
 Bitmap qrCodeBitmap=null;
 try {
 qrCodeBitmap = EncodingHandler.createQRCode(new String(contentString.getBytes(),"iso-8859-1"), 350);
 } catch (UnsupportedEncodingException e) {
 // TODO Auto-generated catch block
 e.printStackTrace();
 }
 
 if(qrCodeBitmap!=null) mImageView.setImageBitmap(qrCodeBitmap);
 else Toast.makeText(this, "解析错误", Toast.LENGTH_SHORT).show();
 }else {
 Toast.makeText(this, "Text can not be empty", Toast.LENGTH_SHORT).show();
 }
 break;
 }
我也尝试了修改EncodingHandler类里面的createQRCode方法,然而并没有什么用
 Hashtable hints = new Hashtable();  
         hints.put(EncodeHintType.CHARACTER_SET, "utf-8"); 
编码格式我换了gbk,iso-8859-1,等一些编码格式都没用,所以只能用我的蠢方法啦~~

     下面我讲讲扫描框的绘制原理

     首先在com.mining.app.zxing.camera包下的CameraManager类中,是调用getFramingRect()方法获取扫描框区域,扫描框越大,所占内存就越大

    

 /**
注释的中文意思大致是:计算解码窗体矩形的控件大小,目的是帮助用户保持足够远以确保图片能被对焦 
 兄弟别纠结,我知道我的翻译烂
   * Calculates the framing rect which the UI should draw to show the user where to place the
   * barcode. This target helps with alignment as well as forces the user to hold the device
   * far enough away to ensure the image will be in focus.
   *
   * @return The rectangle to draw on screen in window coordinates.
   */
  public Rect getFramingRect() {
//获取当前屏幕分辨率
     Point screenResolution = configManager.getScreenResolution();
     if (framingRect == null) {
       if (camera == null) {
         return null;
       }
//计算出扫描框的大小
		 // 	//int width = screenResolution.x * 3 / 4; 为屏幕宽的3/4
 //if (width < MIN_FRAME_WIDTH) {         要注意这里的判断条件,这个MIN_Frame_Width是demo中写死
 //width = MIN_FRAME_WIDTH;                的常量,默认屏幕高度为480*360
// } else if (width > MAX_FRAME_WIDTH) {
 // width = MAX_FRAME_WIDTH;
 // }
 // int height = screenResolution.y * 3 / 4;
 // if (height < MIN_FRAME_HEIGHT) {   为屏幕的高的3/4
 // height = MIN_FRAME_HEIGHT;
 // } else if (height > MAX_FRAME_HEIGHT) {
 // height = MAX_FRAME_HEIGHT;
 // }
 // int leftOffset = (screenResolution.x - width) / 2;//起始位置
 // int topOffset = (screenResolution.y - height) / 2;


//       int width = screenResolution.x/2; //关键是这里才是实际算屏幕高度和宽度的,以便更好的屏 幕适配 //       int height = screenResolution.x/2; //          int leftOffset = (screenResolution.x - width) / 2; //            int topOffset = (screenResolution.y - height) / 2;
       framingRect = new Rect(leftOffset, topOffset, leftOffset + width, topOffset + height);
       Log.d(TAG, "Calculated framing rect: " + framingRect);
    }
    return framingRect;
  }
            到这里你可能就明白扫描框大小是怎么定义的了,但是绘制阴影部分的呢? CameraManager类没有写出来在哪里绘制啊,

      其实自定义扫描框是在com.mining.app.zxing.view包下的ViewfinderView类中,这是一个自定义控件,继承自View的

      学android的大概都知道,绘制样式是在onDraw方法中完成的,以下代码就是绘制边角样式和动态扫描线的地方

@Override
	public void onDraw(Canvas canvas) {
		//中间的扫描框,你要修改扫描框的大小,去CameraManager里面修改
		Rect frame = CameraManager.get().getFramingRect();
		if (frame == null) {
			return;
		}

		//初始化中间线滑动的最上边和最下边
		if(!isFirst){
			isFirst = true;
			slideTop = frame.top;
			slideBottom = frame.bottom;
		}
		
		//获取屏幕的宽和高
		int width = canvas.getWidth();
		int height = canvas.getHeight();

		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 = getResources().getString(R.string.scan_text);  
            float textWidth = paint.measureText(text);  
              
            canvas.drawText(text, (width - textWidth)/2, (float) (frame.bottom + (float)TEXT_PADDING_TOP *density), paint); 
			
			Collection currentPossible = possibleResultPoints;
			Collection currentLast = lastPossibleResultPoints;
			if (currentPossible.isEmpty()) {
				lastPossibleResultPoints = null;
			} else {
				possibleResultPoints = new HashSet(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);
			
		}
	}
    这篇文章主要是我个人的学习记录,也可以方便一下想初步了解Zxing的朋友,因为在网上找的一些分享出来的demo要不就是一运行就崩,要么就是

条形码演示功能没有,要么就是选择图片解析二维码没有。这是我找到的篇较为完整的demo,有很多地方都可以实际应用到项目中,而且注释很全,省得自己再去用蹩脚的英语翻译,再一次感谢作者的分享!

       
  

        

你可能感兴趣的:(学习Zxing的心得)