• Android项目实战(二十八):Zxing二维码实现及优化


    前言:

      多年之前接触过zxing实现二维码,没想到今日项目中再此使用竟然使用的还是zxing,百度之,竟是如此牛的玩意。

      当然,项目中我们也许只会用到二维码的扫描和生成两个功能,所以不必下载完整的jar包,使用简化版的即可,下文可见。

      这篇文章讲述:1、如果快速在项目中集成zxing,实现扫描和生成二维码功能                  

             2、根据项目需求去修改源码实现我们的要求并进行优化

    一、快速集成zxing二维码

    1、下载库文件 : http://download.csdn.NET/detail/u013210620/9036083   ,文件名:BarCodeTest

       下载完成后可以看到:

      

      我们从这些文件中拷贝需要的到自己的项目中,下面开始:

      ①、res 目录下 : raw文件夹 整个复制到个人项目相对位置

      ②、res --> values目录下:ids.xml文件中的内容全部复制到个人项目相对位置,个人项目没有则直接复制文件到相对位置

      ③、res --> values目录下:colors.xml文件中的内容全部复制到个人项目的相对位置

      ④、res --> layout目录下:camera.xml 布局文件复制到个人项目相对位置

      ⑤、res --> drawable_mdpi 目录下:navbar.9.png图片复制到个人项目相对位置,这张图片是标题栏背景图片,这里建议先改成navbar.png 不要使用.9图片 

      ⑥、libs目录下:zxing.jar文件复制到个人项目相对位置,并且右键点击as library

      ⑦、src --> com目录下:zxing 文件夹复制到个人项目相对位置 ,会报错,修改R的目录结构即可

      ⑧、AndroidManifest.xml文件中 添加 (二维码扫描activity,这个需要后面自己去修改,用于实现自己的要求)

     <activity android:name="com.zxing.activity.CaptureActivity"/>

      ⑨、AndroidManifest.xml文件中 添加权限

      <uses-permission android:name="android.permission.CAMERA" />
        <uses-permission android:name="android.permission.VIBRATE" />
        <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
        <uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS" />
      <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />

    2、准备工作完成了,下面开始写demo

      现在需求是一个主界面MainActivity.java 里面有两个按钮,分别跳转 生成二维码界面和 扫描二维码界面

      

      然后分别开始写两个activity功能的实现:

      ①、 生成二维码 

        先写布局文件  ,一个图片 , 一个开始生成按钮 , 一个输入框(二维码需要根据文本信息生成,没有文本信息无法生成)

    <?xml version="1.0" encoding="utf-8"?>
    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:tools="http://schemas.android.com/tools"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical"
        tools:context="com.maiji.zxingdemo.CreateActivity">
    
    
        <ImageView
            android:id="@+id/create_img"
            android:layout_width="300dp"
            android:layout_height="300dp"
            android:scaleType="fitXY"
            android:layout_gravity="center_horizontal"
            />
    
        <Button
            android:id="@+id/create_btn"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="center_horizontal"
            android:text="开始生成二维码"
            />
    
        <EditText
            android:id="@+id/create_edit"
            android:layout_width="match_parent"
            android:layout_height="wrap_content" />
    </LinearLayout>
    activity_create.xml

        activity代码: 代码比较简单 ,不在此解释了

       private ImageView create_img;
        private Button create_btn;
        private EditText create_edit;
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_create);
    
            initView();
            initEvent();
    
        }
    
        private void initEvent() {
            create_btn.setOnClickListener(this);
        }
    
        private void initView() {
            create_img = (ImageView) findViewById(R.id.create_img);
            create_btn = (Button) findViewById(R.id.create_btn);
            create_edit = (EditText) findViewById(R.id.create_edit);
        }
    
        @Override
        public void onClick(View v) {
            switch (v.getId()){
                case R.id.create_btn:
                    String content = "" ;
                    if (create_edit.getText().toString().equals("")){
                        Toast.makeText(this,"请输入二维码信息",Toast.LENGTH_SHORT).show();
                        return;
                    }
                    content = create_edit.getText().toString();
                    try {
                        //生成二维码图片,第一个参数是二维码的内容,第二个参数是正方形图片的边长,单位是像素
                        Bitmap qrcodeBitmap = EncodingHandler.createQRCode(content, 800);
                        if (qrcodeBitmap!=null) {
                            create_img.setImageBitmap(qrcodeBitmap);
                        }else{
                            Toast.makeText(this,"生成二维码失败",Toast.LENGTH_SHORT).show();
                        }
                    } catch (Exception e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    }
                    break;
            }
        }
    
        public byte[] Bitmap2Bytes(Bitmap bm) {
            ByteArrayOutputStream baos = new ByteArrayOutputStream();
            bm.compress(Bitmap.CompressFormat.PNG, 100, baos);
            return baos.toByteArray();
        }

      效果图:

             

     ②、扫描二维码

      这个就更简单了,只需要打开一个zxing提供的activity 然后获取到扫描得到的字符串即可

      看ScanActivity(扫描Activity)的关键代码

    private TextView zxing_content;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_scan);
    zxing_content = (TextView) findViewById(R.id.zxing_content);
    Intent startScan = new Intent(this,CaptureActivity.class);
    startActivityForResult(startScan, 0); //实际打开了一个zxing提供给我们的扫描activity,当然我们后面会对这个activity进行一些优化修改

    }

    /**
    * 扫一扫,成功后返回值进行判断
    */
    @Override
    public void onActivityResult(int requestCode, int resultCode, Intent data) {
    super.onActivityResult(requestCode, resultCode, data);
    if (resultCode == -1) {
    String result = data.getExtras().getString("result");
    zxing_content.setText(result); //显示扫描二维码得到的数据
    }
    }

    布局文件:

    <?xml version="1.0" encoding="utf-8"?>
    <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:tools="http://schemas.android.com/tools"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        tools:context="com.maiji.zxingdemo.ScanActivity">
    
        <TextView
            android:id="@+id/zxing_content"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_centerInParent="true"
            android:textSize="30sp"
            />
    </RelativeLayout>
    activity_scan

    效果图:

            

    二、修改源码,实现项目的需求

    1、修改扫描二维码的界面

      对应的是 zxing-->activity-->CaptureActivity.java   ,布局文件为 camera.xml

      所以修改界面只需要在 camera.xml文件中修改即可。

      无非就是把原来的“CANCEL”取消按钮去掉,把顶部的标题栏换一下。

      布局里面有一个 <SurfaceView>控件 用于显示相机拍出的画面预览,这里可以根据需求改是全界面显示还是显示局部

                <com.zxing.view.ViewfinderView>控件,即扫描框,默认的是宽高比1:1.5,实际需要修改宽高,在下面介绍

    2、修改扫描框的宽高

     第1步操作做完之后会发现,我们没法修改扫描框的宽高。

     修改扫描框宽高很简单,找到 zxing-->camera-->CameraManager.java 文件

     这里较为顶部的代码中看到:

      

      private static final int MIN_FRAME_WIDTH = 240;
      private static final int MIN_FRAME_HEIGHT = 240;
      private static final int MAX_FRAME_WIDTH = 480;
      private static final int MAX_FRAME_HEIGHT = 480;

      这四个属性的值即扫描框的宽高,然后可以根据需求直接修改,当然这个值在不同分辨率的设备上宽高不一致 , 有需要的话可以进行一下单位转换

      

      public static  int Dp2Px( Context context,float dp) {
        final float scale = context.getResources().getDisplayMetrics().density;
        return (int) (dp * scale + 0.5f);
      }

     效果图: 我修改了扫描框的最小最大宽高分别一致,并且载camera.xml布局中删去了“CANCEL”取消按钮

      

    3、给扫描框添加文字提示

      看一下微信的扫描界面,会发现扫描框下面有一段文字提示。 那么我们这里没有,需要添加

      找到zxing-->view-->Viewfinderview.java

      这里是自定义扫描框的类

      找到代码:

      

        canvas.drawRect(frame.left + 2, middle - 1, frame.right - 1, middle + 2, paint);
    
          Collection<ResultPoint> currentPossible = possibleResultPoints;

      在这两行代码之间我们画上文字提示

        canvas.drawRect(frame.left + 2, middle - 1, frame.right - 1, middle + 2, paint);
        TextPaint textPaint = new TextPaint();
          textPaint.setARGB(0xFF, 0xFF, 0xFF,0xFF);   //字体颜色
          textPaint.setTextSize(32);    //字体大小
          textPaint.setAntiAlias(true);  //设置抗锯齿,否则字迹会很模糊
          StaticLayout layout = new StaticLayout("将二维码放入框内,即可自动扫描",textPaint,
                  frame.right-frame.left, Layout.Alignment.ALIGN_NORMAL,1.0F,0.0F,true);
          canvas.translate(frame.left+5, (float) (frame.bottom + (float)30)); //绘制起始位置
          layout.draw(canvas);
        Collection<ResultPoint> currentPossible = possibleResultPoints;

      然后在看下扫描界面效果图:

      

    4、解决扫描界面相机预览拉伸变形问题

          实现了上面几步的优化,仔细的同学可能会发现,如果我们给SurfaceView设置全屏显示(可以看到的相机画面很多),会发现相机拍摄出来的预览图有些拉伸变形

      原因:zxing横屏变竖屏之后,Camera的代码还是采用的横屏代码设置的参数

        优化方法:找到 zxing-->camera--> CameraConfigurationManager.java 

    initFromCameraParameters方法中,
    
    在 Log.d(TAG, "Screen resolution: " + screenResolution);这句之后增加
    Point screenResolutionForCamera = new Point();
    screenResolutionForCamera.x = screenResolution.x;
    screenResolutionForCamera.y = screenResolution.y;
            
    if (screenResolution.x < screenResolution.y) {
    screenResolutionForCamera.x = screenResolution.y;
    screenResolutionForCamera.y = screenResolution.x;
     }
    再将cameraResolution = getCameraResolution(parameters, screenResolution);
    
    更改为
    
    cameraResolution = getCameraResolution(parameters, screenResolutionForCamera);

     完成之后,在进行扫描操作,这时候相机拍出来的预览界面就正常显示,不再有拉伸变形问题。

     至此便给项目引入了一个可以使用的二维码模块功能了。

  • 相关阅读:
    java实现扑克牌排列
    java实现扑克牌排列
    java实现扑克牌排列
    java实现扑克牌排列
    java实现扑克牌排列
    java实现平面点最小距离
    java实现平面点最小距离
    java实现拍7游戏
    java实现拍7游戏
    using_where, Using temporary ,using_filesort 分享
  • 原文地址:https://www.cnblogs.com/xqxacm/p/6078729.html
Copyright © 2020-2023  润新知