博主有话说:写这个博客只是为了记录学习android过程中的问题,这篇文章只是参考了很多其他博主写的文章和资料总结出的笔记,并非完全原创。如果你运气不咋地看到这篇文章而且又觉得似曾相识,请勿喷我,我会在文章最后贴出参考博客地址。
关于zxing库,有以下几个方面:
(1)下载zxing库(下载精简过的android库)
(2)配置zxing库到项目中
(3)生成二维码
(4)扫描二维码
(5)扫描框UI
(1)下载zxing库
尊重原作者:https://github.com/zxing/zxing
但是因为原作者实在是太厉害,库实在太大,所以请下载精简过的zxing库,以下是精简库的结构:
(2)配置zxing库到项目中
①将下载的zxing库import进eclipse中
②选中该项目右键——properties——Android——选中isLibrary(因为这个项目作为库被其他项目使用)——OK
③新建一个项目(这个项目是你需要导入这个功能的项目)
④选中该项目右键——properties——Android——Add加入zxing库——OK
(3)生成二维码
①创建EditText et1接受输入内容
String str =et1.getText().toString();
②创建Bitmap存储二维码图片,而生成二维码是用到库里面的EncodingHandler类中的createQRCode方法
Bitmap qrcode = EncodingHandler.createQRCode(et1.getText().toString(), 400);
参数:
1.生成二维码的内容
2.生成二维码横向纵向长度(由于是一个正方形,所以只有一个值)
完整代码:
String str =et1.getText().toString();
if(str.equals("")){
Toast.makeText(MainActivity.this, "请输入文本", Toast.LENGTH_SHORT).show();
}
else{
try {
//第一个参数是要生成二维码的内容,第二个参数是生成二维码横向纵向长度
Bitmap qrcode = EncodingHandler.createQRCode(et1.getText().toString(), 400);
iv.setImageBitmap(qrcode);
} catch (WriterException e) {
e.printStackTrace();
}
}
(4)扫描二维码
①二维码扫描的页面实际是库里面的一个Activity,项目里面通过跳转到库里面CaptureActivity来使用二维码扫描功能,所以要定义一个intent来跳转。
Intent startScan = new Intent(MainActivity.this, CaptureActivity.class);
②实现跳转功能需要在你的项目AndroidManifest.xml中定义Activity,可以直接把zxing库中AndroidManifest.xml的以下内容复制到你的项目AndroidManifest.xml中
③调用startActivity(startScan);跳转到二维码扫描页面,扫描页面如下(这是改变过的UI)
完整代码:
Intent startScan = new Intent(MainActivity.this, CaptureActivity.class);
startActivity(startScan);
但是调用startActivity(startScan);只能打开扫描Activity,但是不能解码,由于库的CaptureActivity中的handleDecode方法会将解码内容回调,如下:
public void handleDecode(Result result, Bitmap barcode) {
inactivityTimer.onActivity();
playBeepSoundAndVibrate();
String resultString = result.getText();
if (resultString.equals("")) {
Toast.makeText(CaptureActivity.this, "Scan failed!", Toast.LENGTH_SHORT).show();
}else {
Intent resultIntent = new Intent();
Bundle bundle = new Bundle();
bundle.putString("result", resultString);
resultIntent.putExtras(bundle);
this.setResult(RESULT_OK, resultIntent);
}
CaptureActivity.this.finish();
}
所以在你的项目的MainActivity需要调用startActivityForResult(startScan, 0);来跳转页面且使用onActivityResult方法接收回调的内容,用TextView tv1显示出来,如下:
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if(resultCode ==RESULT_OK){
String str =data.getExtras().getString("result");
tv1.setText(str);
}
}
完整代码:
public class MainActivity extends Activity {
private Button bt1,bt2;
private TextView tv1;
private EditText et1;
private ImageView iv;
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
bt1 =(Button)findViewById(R.id.bt1);
bt2 =(Button)findViewById(R.id.bt2);
tv1 =(TextView)findViewById(R.id.tv1);
et1 =(EditText)findViewById(R.id.et1);
iv =(ImageView)findViewById(R.id.iv1);
bt1.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
Toast.makeText(MainActivity.this, "你写可以扫描条形码或者二维码", Toast.LENGTH_SHORT).show();
Intent startScan = new Intent(MainActivity.this, CaptureActivity.class);
//startActivity(startScan);
startActivityForResult(startScan, 0);
}
});
bt2.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
String str =et1.getText().toString();
if(str.equals("")){
Toast.makeText(MainActivity.this, "请输入文本", Toast.LENGTH_SHORT).show();
}
else{
try {
//第一个参数是要生成二维码的内容,第二个参数是生成二维码横向纵向长度
Bitmap qrcode = EncodingHandler.createQRCode(et1.getText().toString(), 400);
iv.setImageBitmap(qrcode);
} catch (WriterException e) {
e.printStackTrace();
}
}
}
});
}
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if(resultCode ==RESULT_OK){
String str =data.getExtras().getString("result");
tv1.setText(str);
}
}
}
由于扫描功能用到照相机,和震动,需要加入permission:
演示:
①在EditText输入需要转换内容,点击生成二维码生成。
②点击打开扫描二维码按钮,扫描,显示输入的内容
(5)扫描框UI
由于库中自带的扫描框是横屏的,解决横屏和其他详见问题参考:
http://www.cnblogs.com/dolphin0520/p/3355728.html
扫描框其实是通过View画出来的,在zxing库中的包com.zxing.view的ViewfinderView类就是扫描框的UI,由于对View不怎么熟悉,只能凭我自己理解。
1.包 com.zxing.camera的CameraManager类中以下两个参数是可以控制框的大小
//控制框的最大宽度
private static final int MAX_FRAME_WIDTH = 480;
//控制框的最大高度
private static final int MAX_FRAME_HEIGHT = 480;
2.包com.zxing.view的ViewfinderView类中以下代码获取到这个框
Rect frame = CameraManager.get().getFramingRect();
if (frame == null) {
return;
}
3在ondraw方法中对获得的框进行装饰
①绘制扫描框以外的阴影部分
// 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);
② 画出扫描框的四个角
paint.setColor(getResources().getColor(R.color.blues));
//左上角
canvas.drawRect(frame.left,frame.top, frame.left + ScreenRate,frame.top+ 10,paint);
canvas.drawRect(frame.left,frame.top, frame.left + 10,frame.top+ ScreenRate,paint);
//右上角
canvas.drawRect(frame.right- ScreenRate,frame.top, frame.right,frame.top + 10,paint);
canvas.drawRect(frame.right- 10,frame.top, frame.right,frame.top + ScreenRate,paint);
//左下角
canvas.drawRect(frame.left,frame.bottom - 10,frame.left + ScreenRate,frame.bottom,paint);
canvas.drawRect(frame.left,frame.bottom - ScreenRate,frame.left + 10,frame.bottom,paint);
//右下角
canvas.drawRect(frame.right- ScreenRate,frame.bottom - 10,frame.right,frame.bottom, paint);
canvas.drawRect(frame.right- 10,frame.bottom - ScreenRate,frame.right,frame.bottom, paint);
③绘制框中移动的线(可以用图片实现)
//初始化中间线滑动的最上边和最下边
if(!isFirst){
isFirst = true;
slideTop = frame.top;
slideBottom = frame.bottom;
}
//绘制中间的线,每次刷新界面,中间的线往下移动SPEEN_DISTANCE
slideTop += SPEEN_DISTANCE;
if(slideTop >= frame.bottom){
slideTop = frame.top;
}
canvas.drawRect(frame.left + MIDDLE_LINE_PADDING, slideTop - MIDDLE_LINE_WIDTH/2, frame.right - MIDDLE_LINE_PADDING,slideTop + MIDDLE_LINE_WIDTH/2, paint);
④画扫描框的边框
// Draw a two pixel solid black border inside the framing rect
paint.setColor(frameColor);
canvas.drawRect(frame.left, frame.top, frame.right + 1, frame.top + 2, paint);
canvas.drawRect(frame.left, frame.top + 2, frame.left + 2, frame.bottom - 1, paint);
canvas.drawRect(frame.right - 1, frame.top, frame.right + 1, frame.bottom - 1, paint);
canvas.drawRect(frame.left, frame.bottom - 1, frame.right + 1, frame.bottom + 1, paint);
⑤画扫描框下面的字
paint.setColor(Color.BLACK);
paint.setTextSize(TEXT_SIZE * density);
paint.setAlpha(0x40);
paint.setTypeface(Typeface.create("System", Typeface.BOLD));
canvas.drawText(getResources().getString(R.string.scan_text), frame.left, (float) (frame.bottom + (float)TEXT_PADDING_TOP *density), paint);
⑥在扫描的时候,框里面会出现一些黄色点,将以下代码注释掉就不会有了
for (ResultPoint point : currentPossible) {
canvas.drawCircle(frame.left + point.getX(), frame.top + point.getY(), 6.0f, paint);
}
问题(这是为了提醒博主以后深入研究的问题)
①手机离二维码很近的时候反而不能扫描出二维码,在一定距离后才能正常扫描出二维码(可能与内部算法有关)。
②扫描框下字体颜色很暗,即使用了WITHE,(可能是因为在绘制阴影部分的时候,掩盖了字体的颜色,需要去看看View详解),所以在这里直接用TextView 在camera.xml写出来。缺点是当扫描框大小改变的时候,TextView位置不改变。
③中间移动的线在扫描时候不平滑
④...
参考网址与博客:
http://www.cnblogs.com/dolphin0520/p/3355728.html
http://blog.csdn.net/xiaanming/article/details/10163203?D2kdVYKfPI_-8QXCzICABQ&ved=0CBkQFjABOIwB&usg=AFQjCNF2ULtaIMPd5bndaol7tFI3AO61Xw
http://blog.csdn.net/xinchen200/article/details/18036695
http://www.jikexueyuan.com/course/134_3.html?ss=1