Android:实际运用Zxing集成二维码扫描 及 自定义扫码界面(demo源码)

本文详细介绍如何将Zxing开源库集成到项目中,并自定义扫码界面,包括头部、扫描框及底部功能按钮的设计与实现。同时介绍了如何生成二维码及处理扫码数据。

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

二维码扫描,各大主流App必不可少的功能,而且google已将轮子替我们造好,直接拿来使用即可。以下是教学如何将Zxing开源库集成到自己项目中,并且自定义扫码界面,后期可根据自己的业务需求进行修改,最后补充了一点由此延伸的学习技能点。

一. 集成Zing开源库到应用中

这里写图片描述

这里写图片描述

如上图所示,我使用的集成方法是拷入jar包,然后拷贝相关类即可,具体的资源都已经在Demo中做好了,具体内容都可以直接参考Demo。(看到网上还有其它集成的方法,虽没试过,各位也可以考虑)

  • app 扫描Activity
  • camera 摄像头相关
  • decode 解析二维码相关
  • encode 生成二维码相关
  • util 工具类
  • view 扫描预览视图ViewfinderView




二. 自定义扫码界面

这里写图片描述

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent" >

    <RelativeLayout
        android:layout_width="fill_parent"
        android:layout_height="fill_parent" >

        <SurfaceView
            android:id="@+id/preview_view"
            android:layout_width="fill_parent"
            android:layout_height="fill_parent"
            android:layout_gravity="center" />

        <cn.edu.wsyu.hgh.zhiliao.component.zxing.view.ViewfinderView
            android:id="@+id/viewfinder_view"
            android:layout_width="fill_parent"
            android:layout_height="fill_parent" />
    </RelativeLayout>

</FrameLayout>

如果集成Zxing成功后打开扫描功能,你会发现扫描页面如上图所示,这是CaptureActivity的布局,CaptureActivity主要来处理扫描界面的逻辑。布局仅有一个SurfaceView,中间一个供扫描的矩形框ViewfinderView就目前而言,扫描的功能已经可以使用了,但是这种UI效果是市场上的app不符,所以需要自定义扫码页面,而理想实现效果如下图所示:

这里写图片描述

1. 需要实现的需求

对比以上两张图,总结出我们需要实现的需求

  • (1) 增加一个toolbar,内容填充为返回键和界面提示。
  • (2) 中间的扫描区域—–即Zxing为我们绘制的矩形的四个角上分别画了8个绿色小矩形和一条不停上下移动的扫描线。
  • (3) 在最下方加了一个footer,增加了相册、开灯两个功能使得这个扫描功能更加完善。

经过以上分析可得,完成上述3个需求,就可以达到理想的UI效果了,接下来依次实现:



2. 实现头部效果

这里写图片描述

这个头部实现实在很简单,这里不过多赘述,提供2种实现思路:

  • 1 使用Android提供控件Toolbar,在控件中再加一个TextView用来显示“扫一扫”即可。
  • 2 直接加一个布局View,布局中一个ImageView、TextView完成

布局完成后,在CaptureActivity中设置对应的点击事件,处理返回逻辑即可。



3. 实现扫描框效果

这里写图片描述

这个扫描框是Zxing自带的一个自定义View,名为ViewfinderView,而目前需要做的需求:

  • 1 扫码框的四个角上,每个角有两条边,总共八条,绘制8条绿色矩形,完成边框。
  • 2 在扫码框中绘制一条不停上下移动的线。
  • 3 在扫描框下方添加一条提示语句

3.1 绘制扫描边框

熟悉自定义View的人首先想到在ViewfinderView中的onDraw方法中完成绘制,首先来看它默认绘制的onDraw方法:

 @Override
    public void onDraw(Canvas canvas) {
       //获得扫描框的矩形
        Rect frame = CameraManager.get().getFramingRect();
        if (frame == null) {
            return;
        }

        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);

        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);
        }

初步了解后,需要使用canvas来绘制8个小矩形,代码不难如下

paint.setColor(Color.BLUE);
            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);

这值得注意的是ScreenRate,即小矩形的长度,这里并没有把它固定化,而是将理想值乘以屏幕密度,来更好地适配不同大小屏幕:

            density = context.getResources().getDisplayMetrics().density;
            ScreenRate = (int) (15 * density);

3.2 绘制移动的线

  //定义好扫描线每秒移动端的像素
            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.fle))).getBitmap(), null, lineRect,
                    paint);

3.3 绘制文字

  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);



三. 扫码功能完善

1. 扫码界面功能完善

以上界面完成后,需要在CaptureActivity中稍加完善几个按钮(开闪光灯、相册)的功能:
之所以选择Zxing开源库的一大原因是因为它将所有的方法都封装完善,只需我们调用即可,例如开启或关闭闪光灯。

     @Override
    public void onClick(View v) {
        switch (v.getId()) {
            case R.id.flash_btn:// 闪光灯开关
                if (isTorchOn) {
                    isTorchOn = false;
                    flash_btn.setText("关灯");
                    CameraManager.start();
                } else {
                    isTorchOn = true;
                    flash_btn.setText("开灯");
                    CameraManager.stop();
                }
                break;
            case R.id.photo_btn: {// 选择相册
                selectPhoto();
            }
            break;
            case R.id.button_back: {// 返回
                finish();
            }
            break;
            default:
                break;
        }
    }


2 主页跳转到扫码界面

MainActivity

    private static final int REQUEST_QRCODE = 0x01;

    Intent intent = new Intent(mContext, CaptureActivity.class);
    startActivityForResult(intent, REQUEST_QRCODE);

以上代码非常简单,假设是在MainActivity中进行操作,点击对应按钮进入到CaptureActivity中,唯一需要注意的是跳转页面使用的方法是startActivityForResult,因为我们需要获取到扫描后的数据,然后做下一步的处理。



3二维码生成

生成二维码的方式:

   /**
     * 二维码生成
     */
    private void qrCodeGenerated() {

        String str = "点个赞噻";

        DisplayMetrics metric = new DisplayMetrics();
        getWindowManager().getDefaultDisplay().getMetrics(metric);
        int width = metric.widthPixels;
        try {

            Bitmap qrCode = Utils.createQRCode(str, width / 2);
            qrcodeImg.setImageBitmap(qrCode);

        } catch (WriterException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }

str代表二维码中的数据,主要依赖的是Util工具类的方法,其中还有二维码中含Logo的方式,自己可修改,两种方法如下:

    /**
     * 生成一个二维码图像
     * 
     * @param url
     *            传入的字符串,通常是一个URL
     * @param widthAndHeight
     *            图像的宽高
     * @return
     */
    private static final int BLACK = 0xff000000;

    public static Bitmap createQRCode(String str, int widthAndHeight)
    /**
     * 生成一个有logo的二维码图像
     * 
     * @param url
     *            传入的字符串,通常是一个URL
     * @param widthAndHeight
     *            图像的宽高
     * @return
     */

    public static Bitmap createQRCodeLogo(String str, int widthAndHeight,
                                          Bitmap bit)


4. 主页获取扫码数据并处理

要想在MainActivity 中的 onActivityResult方法获取到扫描的数据,必须要知道什么时候将数据setResult进来的,获取数据的Key值是什么?

解析二维码是个耗时的操作,必然在子线程中执行,所以我们直接查看CaptureActivity对应的Handle——CaptureActivityHandle,通过类注释可知,这个类负责处理所有扫码相关的业务,既然是个Handle,那我们直接来看handleMessage方法:

 @Override
    public void handleMessage(Message message) {

        ......

       case R.id.decode_succeeded:// 解码成功
            Log.d(TAG, "Got decode succeeded message");
            state = State.SUCCESS;
            Bundle bundle = message.getData();

            /****************************************************/
            Bitmap barcode = bundle == null ? null : (Bitmap) bundle
                    .getParcelable(DecodeThread.BARCODE_BITMAP);

            //将扫码后得的数据返回给CaptureActivity去处理
            activity.handleDecode((Result) message.obj, barcode);
            break;

        ...... 
    }

handleMessage方法中考虑了好几种情况,我们只需要了解这一种即可,将状态标记为“成功”,将扫码后得的数据返回给CaptureActivity去处理,所以最后还是回到CaptureActivityhandleDecode方法:

    /**
     * 处理扫描结果
     *
     * @param result
     * @param barcode
     */
    public void handleDecode(Result result, Bitmap barcode) {
        inactivityTimer.onActivity();
        playBeepSoundAndVibrate();
        String resultString = result.getText();
        if (resultString.equals("")) {
            Toast.makeText(this, "扫描失败!", Toast.LENGTH_SHORT)
                    .show();
        } else {
            Intent data = new Intent();
            data.putExtra("SCAN_RESULT", resultString);
            setResult(RESULT_OK, data);
            finish();
        }
    }

主要逻辑为将获取到扫码后的数据放入到Intent中,结束当前扫码页面。重要的是:我们获取到了Key值:SCAN_RESULT此时,我们可以在MainActivity中获取到扫码后的数据并处理它。以上只是举一个实例,不仅这个Key值,还有其余需要使用的都可在CaptureActivity找到,如下表格:

含义KeyresultCode
直接扫码后获得的数据SCAN_RESULTActivity.RESULT_OK
相册图片扫码后获得的数据LOCAL_PHOTO_RESULT300
    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        switch (requestCode) {
            case REQUEST_QRCODE:
                if (resultCode == Activity.RESULT_OK) {
                    //扫描后的业务逻辑
                    String code = data.getStringExtra("SCAN_RESULT");
                    if (code.contains("http") || code.contains("https")) {
                        //打开链接
                        /*Intent intent = new Intent(this, AdBrowserActivity.class);
                        intent.putExtra(AdBrowserActivity.KEY_URL, code);
                        startActivity(intent);*/
                        Toast.makeText(this, code, Toast.LENGTH_SHORT).show();

                    } else {
                        Toast.makeText(this, code, Toast.LENGTH_SHORT).show();
                    }
                }else if(resultCode == 300){
                    //从本地相册扫描后的业务逻辑
                    String code = data.getStringExtra("LOCAL_PHOTO_RESULT");
                    Toast.makeText(this, code, Toast.LENGTH_SHORT).show();
                }
                break;
        }

    }

以上代码通过Key值获取到扫码后的数据data.getStringExtra("SCAN_RESULT")。这里多做了一个判断,如果数据包含http或者https时,可以用浏览器打开,这用用户体验会更好,当然,你也可以按照自己的想法去处理。




四. 拓展学习——闪光灯使用

在集成使用一个开源库时,可是适当学习它的源码设计、封装风格等等,例如Zxing中已实现的使用闪光灯,单独将此代码拿出来,平常在开发中也会有使用到闪光灯的场景,大可以将此方法放到自己的工具库中,使用的时候调用即可,此刻可以很好的参考参考大神封装的方法:

CameraManager.java

    private Camera camera;
    public static void init(Context context) {
        if (cameraManager == null) {
            cameraManager = new CameraManager(context);
        }
    }

    /**
     * 通过设置Camera打开闪光灯
     */
    public void turnLightOn() {
        if (camera == null) {
            return;
        }
        Parameters parameters = camera.getParameters();
        if (parameters == null) {
            return;
        }

        List<String> flashModes = parameters.getSupportedFlashModes();
        if (flashModes == null) {
            return;
        }
        String flashMode = parameters.getFlashMode();
        Log.i(TAG, "Flash mode: " + flashMode);
        Log.i(TAG, "Flash modes: " + flashModes);
        // 闪光灯关闭状态
        if (!Parameters.FLASH_MODE_TORCH.equals(flashMode)) {
            // Turn on the flash
            if (flashModes.contains(Parameters.FLASH_MODE_TORCH)) {
                parameters.setFlashMode(Parameters.FLASH_MODE_TORCH);
                camera.setParameters(parameters);
                camera.startPreview();
            } else {
            }
        }
    }

    /**
     * 通过设置Camera关闭闪光灯
     * 
     * @param mCamera
     */
    public void turnLightOff() {
        if (camera == null) {
            return;
        }
        Parameters parameters = camera.getParameters();
        if (parameters == null) {
            return;
        }
        List<String> flashModes = parameters.getSupportedFlashModes();
        String flashMode = parameters.getFlashMode();
        // Check if camera flash exists
        if (flashModes == null) {
            return;
        }
        // 闪光灯打开状态
        if (!Parameters.FLASH_MODE_OFF.equals(flashMode)) {
            // Turn off the flash
            if (flashModes.contains(Parameters.FLASH_MODE_OFF)) {
                parameters.setFlashMode(Parameters.FLASH_MODE_OFF);
                camera.setParameters(parameters);
            } else {
                Log.e(TAG, "FLASH_MODE_OFF not supported");
            }
        }
    }



最后附加一点自己的最近的想法:

最近这几个月写博客写的不像初学Android时那么勤了,与同伴在做一个App,项目中用了不少开源库,这个Zxing也是其中一个。写完这篇博客不由得扪心自问,这些东西仅仅停留在会使用的阶段,不算是真正的学习,就像我这篇博客,是一篇参考型文章,并非学习类文章,通篇看下来也不会有恍然大悟的感觉,作为笔者的我感觉也没有深层次的学到什么,正如很多大牛说过的:许多开源库不是会用就够了,我们还需要学习它的实现封装等等,这才能使我们进步(鸡汤奉上)……

所以接下来打算学习一些偏向底层的干货,缓解近期的迷茫。将自己的想法分享给各位志同道合的friends,在未来杠 Android的路上继续努力,哈哈哈~


希望对你们有帮助 :)


源码奉上~~
ZxingDemo源码

二维码现在越来越火爆,使用的越发广泛,对于二维码二维码的生成与解析,有多种途径,这里我选择用google老大的ZXing。    其中刘超大神使用ZXing写了一个快速集成二维码扫描的工具类,实现其核心的实现扫描的功能。使用时通过调用二维码工具类,几行代就可以实现二维码扫描的功能! 一、实现对二维码扫描 使用步骤: 1.在module的build.gradle中dependencies添加 compile 'cn.yipianfengye.android:zxing-library:2.1' 2.在Application中执行初始化操作 提示:在清单文件中注册Application public class MyApplication extends Application{ @Override public void onCreate() { super.onCreate(); //初始化二维码工具类 ZXingLibrary.initDisplayOpinion(this); } } 3.在清单文件配置权限(安卓6.0以上的手机还要额外的权限配置)。 <uses-permission android:name="android.permission.CAMERA" /> <uses-permission android:name="android.permission.FLASHLIGHT" /> <uses-feature android:name="android.hardware.camera" /> <uses-feature android:name="android.hardware.camera.autofocus" /> <uses-permission android:name="android.permission.VIBRATE" /> <uses-permission android:name="android.permission.WAKE_LOCK" /> <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" /> <uses-permission android:name="android.permission.INTERNET" /> 4.在代中执行打开扫描二维码界面操作  Intent intent = new Intent(MainActivity.this, CaptureActivity.class); startActivityForResult(intent, REQUEST_CODE); 这里的REQUEST_CODE是我们定义的int型常量,这里设置为5,为了方便接受onActivityResult分别进行处理。 5.在Activity的onActivityResult方法中接收扫描结果(下面有完整代) protected void onActivityResult(int requestCode, int resultCode, Intent data) { if (requestCode == 5) { if (null != data) { Bundle bundle = data.getExtras(); if (bundle == null) { return; } if (bundle.getInt(CodeUtils.RESULT_TYPE) == CodeUtils.RESULT_SUCCESS) { String result = bundle.getString(CodeUtils.RESULT_STRING); Toast.makeText(this, "解析结果:" + result, Toast.LENGTH_LONG).show(); } else if (bundle.getInt(CodeUtils.RESULT_TYPE) == CodeUtils.RESULT_FAILED) { Toast.makeText(MainActivity.this, "解析二维码失败", Toast.LENGTH_LONG).show(); } } } } 实现效果:(由于模拟器没有摄像头不能扫描二维码,手机录屏需要root,所以就截取了效果图) 第一张是进行二维码扫描,第二张是当扫描结束,显示信息。 只用区区几行代,就可以实现二维码的快速扫描。 二、定制化显示扫描UI 1.在values的colors文件下添加颜色,决定了二维码四个边框的颜色 <color name="scan_corner_color">#0effc2</color>2. 2.在drawable文件下添加一个scan_image.png的图片,就是二维码扫描的那条横线 3.创建一个新的Activity(demo里叫 SecondActivity )集成FragmentActivity,在清单文件里进行配置。 4. 修改新的Activity布局文件,是二维码的背景布局 <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/activity_second" android:layout_width="match_parent" android:layout_height="match_parent"> <Button android:id="@+id/second_button1" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="bottom|center_horizontal" android:layout_marginBottom="10dp" android:layout_marginLeft="20dp" android:layout_marginRight="20dp" android:layout_marginTop="20dp" android:text="取消二维码扫描" /> <FrameLayout android:id="@+id/fl_my_container" android:layout_width="match_parent" android:layout_height="match_parent"> </FrameLayout> </FrameLayout> 技术点:启动id为fl_my_container的FrameLayout就是我们需要替换的扫描组件,也就是说我们 会将我们定义的扫描Fragment替换到id为fl_my_container的FrameLayout的位置。 而上面的button是我们添加的一个额外的控件,在这里你可以添加任意的控件,各种UI效果等。 5. 创建my_camera.xml布局文件,这个就是扫描二维码界面自定义二维码扫描页面,就在这个布局里进行修改,这里我加了一个ToolBar,一个Button按钮 用来退出扫描。 <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" android:layout_width="fill_parent" android:layout_height="fill_parent"> <SurfaceView android:id="@+id/preview_view" android:layout_width="wrap_content" android:layout_height="wrap_content" /> <android.support.v7.widget.Toolbar android:background="#FF0000" android:layout_width="match_parent" android:layout_height="100dp"> </android.support.v7.widget.Toolbar> <com.uuzuche.lib_zxing.view.ViewfinderView android:id="@+id/viewfinder_view" android:layout_width="wrap_content" android:layout_height="wrap_content" app:inner_corner_color="@color/scan_corner_color" app:inner_corner_length="30dp" app:inner_corner_width="5dp" app:inner_height="200dp" app:inner_margintop="150dp" app:inner_scan_bitmap="@drawable/scan_image" app:inner_scan_iscircle="false" app:inner_scan_speed="10" app:inner_width="200dp" /> </FrameLayout> 6. 二维码解析回调函数,代放到SecondActivity CodeUtils.AnalyzeCallback analyzeCallback = new CodeUtils.AnalyzeCallback() { @Override public void onAnalyzeSuccess(Bitmap mBitmap, String result) { Intent resultIntent = new Intent(); Bundle bundle = new Bundle(); bundle.putInt(CodeUtils.RESULT_TYPE, CodeUtils.RESULT_SUCCESS); bundle.putString(CodeUtils.RESULT_STRING, result); resultIntent.putExtras(bundle); SecondActivity.this.setResult(RESULT_OK, resultIntent); SecondActivity.this.finish(); } @Override public void onAnalyzeFailed() { Intent resultIntent = new Intent(); Bundle bundle = new Bundle(); bundle.putInt(CodeUtils.RESULT_TYPE, CodeUtils.RESULT_FAILED); bundle.putString(CodeUtils.RESULT_STRING, ""); resultIntent.putExtras(bundle); SecondActivity.this.setResult(RESULT_OK, resultIntent); SecondActivity.this.finish(); } }; 7.在Activity中执行Fragment的初始化操作 @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_second); initView(); //在Activity中执行Fragment的初始化操作 //执行面Fragment的初始化操作 CaptureFragment captureFragment = new CaptureFragment(); // 为二维码扫描界面设置定制化界面 CodeUtils.setFragmentArgs(captureFragment, R.layout.my_camera); captureFragment.setAnalyzeCallback(analyzeCallback); getSupportFragmentManager().beginTransaction().replace(R.id.fl_my_container, captureFragment).commit(); } 8.使用Activity里定义的Button按钮,完成用户通过点击,退出二维码扫描界面的操作 //点击退出按钮就退出扫描二维码界面 @Override public void onClick(View v) { switch (v.getId()) { case R.id.second_button1: finish(); break; } } 效果图: 完整代(布局只有两个Button): MainActivity: /*使用二维码工具类步骤: * 1. 在module的build.gradle中dependencies添加:compile 'cn.yipianfengye.android:zxing-library:2.1' * 2. 在Application中执行二维码工具类的初始化操作 ZXingLibrary.initDisplayOpinion(this); * 3. 在清单文件配置权限和自定义的APPlication,安卓6.0的手机还要做额外的权限配置,方有效. * 3. 更加点击事件调用开启扫描二维码界面操作 * 4. 在自动接收跳转页面传过来的数据onActivityResult里接收扫描结果,并对结果进行处理 * */ public class MainActivity extends AppCompatActivity implements View.OnClickListener { private Button ZXing; private Button ZXingOK; private Button ZXingOK2; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); initView(); } private void initView() { ZXing = (Button) findViewById(R.id.ZXing); ZXingOK = (Button) findViewById(R.id.ZXingOK); ZXing.setOnClickListener(this); ZXingOK.setOnClickListener(this); ZXingOK2 = (Button) findViewById(R.id.ZXingOK2); ZXingOK2.setOnClickListener(this); } //根据点击事件开启二维码扫描,这里的5是为了方便接受onActivityResult分别进行处理 @Override public void onClick(View v) { switch (v.getId()) { case R.id.ZXing: Intent intent = new Intent(MainActivity.this, CaptureActivity.class); startActivityForResult(intent, 5); break; case R.id.ZXingOK: Intent intent1 = new Intent(MainActivity.this, SecondActivity.class); startActivityForResult(intent1, 7); break; case R.id.ZXingOK2: Intent intent2 = new Intent(MainActivity.this, Main2Activity.class); startActivity(intent2); break; } } //在自动接收跳转页面传过来的数据OnActivityResult里接收扫描结果,并对结果进行处理 @Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { //处理二维码扫描的结果,5就是对在startActivityForResult里设置的标识进行判断,执行对应的逻辑 if (requestCode == 5) { //处理扫描结果(在界面上显示) if (null != data) { Bundle bundle = data.getExtras(); if (bundle == null) { return; } if (bundle.getInt(CodeUtils.RESULT_TYPE) == CodeUtils.RESULT_SUCCESS) { String result = bundle.getString(CodeUtils.RESULT_STRING); Toast.makeText(this, "解析结果:" + result, Toast.LENGTH_LONG).show(); } else if (bundle.getInt(CodeUtils.RESULT_TYPE) == CodeUtils.RESULT_FAILED) { Toast.makeText(MainActivity.this, "解析二维码失败", Toast.LENGTH_LONG).show(); } } } if (requestCode == 7) { if (null != data) { Bundle bundle = data.getExtras(); if (bundle == null) { return; } if (bundle.getInt(CodeUtils.RESULT_TYPE) == CodeUtils.RESULT_SUCCESS) { String result = bundle.getString(CodeUtils.RESULT_STRING); Toast.makeText(this, "解析结果:" + result, Toast.LENGTH_LONG).show(); } else if (bundle.getInt(CodeUtils.RESULT_TYPE) == CodeUtils.RESULT_FAILED) { Toast.makeText(MainActivity.this, "解析二维码失败", Toast.LENGTH_LONG).show(); } } } } } SecondActivity: /* 定制化显示扫描界面 * 1.在values的colors文件下添加颜色,决定了二维码四个边框的颜色 * 2.在drawable文件下添加一个scan_image.png的图片,决定了二维码扫描的那条横线的颜色 * 3.创建一个新的Activity(demo里叫 SecondActivity )集成FragmentActivity,在清单文件里进行配置. * 4.修改新的Activity布局文件,是二维码的背景布局 * 5.创建my_camera.xml布局文件,这个就是扫描二维码界面 * 6.二维码解析回调函数,代放到这个Activity即可(SecondActivity就在这个Activity名字) * 7.在Activity中执行Fragment的初始化操作 * 8.使用Activity里定义的Button按钮,完成用户通过点击,退出二维码扫描界面的操作. * 9.使用这个我们自定义二维码扫描界面和使用默认的界面类似,只需替换CaptureActivity即可 */ public class SecondActivity extends AppCompatActivity implements View.OnClickListener { private Button second_button1; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_second); initView(); //在Activity中执行Fragment的初始化操作 //执行面Fragment的初始化操作 CaptureFragment captureFragment = new CaptureFragment(); // 为二维码扫描界面设置定制化界面 CodeUtils.setFragmentArgs(captureFragment, R.layout.my_camera); captureFragment.setAnalyzeCallback(analyzeCallback); getSupportFragmentManager().beginTransaction().replace(R.id.fl_my_container, captureFragment).commit(); } private void initView() { second_button1 = (Button) findViewById(R.id.second_button1); second_button1.setOnClickListener(this); } //点击退出按钮就退出扫描二维码界面 @Override public void onClick(View v) { switch (v.getId()) { case R.id.second_button1: finish(); break; } } //二维码解析回调函数,代放到这个Activity即可(SecondActivity就在这个Activity名字) CodeUtils.AnalyzeCallback analyzeCallback = new CodeUtils.AnalyzeCallback() { @Override public void onAnalyzeSuccess(Bitmap mBitmap, String result) { Intent resultIntent = new Intent(); Bundle bundle = new Bundle(); bundle.putInt(CodeUtils.RESULT_TYPE, CodeUtils.RESULT_SUCCESS); bundle.putString(CodeUtils.RESULT_STRING, result); resultIntent.putExtras(bundle); SecondActivity.this.setResult(RESULT_OK, resultIntent); SecondActivity.this.finish(); } @Override public void onAnalyzeFailed() { Intent resultIntent = new Intent(); Bundle bundle = new Bundle(); bundle.putInt(CodeUtils.RESULT_TYPE, CodeUtils.RESULT_FAILED); bundle.putString(CodeUtils.RESULT_STRING, ""); resultIntent.putExtras(bundle); SecondActivity.this.setResult(RESULT_OK, resultIntent); SecondActivity.this.finish(); } }; } 三、生成二维码 只需要在点击事件中加入相应执行代,即可完成效果: @Override public void onClick(View v) { switch (v.getId()) { //生成不带logo的二维码图片 case R.id.btnStart: String textContent = edShow.getText().toString(); if (TextUtils.isEmpty(textContent)) { Toast.makeText(Main2Activity.this, "您的输入为空!", Toast.LENGTH_SHORT).show(); return; } edShow.setText(""); Bitmap image = CodeUtils.createImage(textContent, 400, 400, null); imgShow.setImageBitmap(image); break; //生成带logo的二维码图片 case R.id.btnStart2: String textContent1 = edShow.getText().toString(); if (TextUtils.isEmpty(textContent1)) { Toast.makeText(Main2Activity.this, "您的输入为空!", Toast.LENGTH_SHORT).show(); return; } edShow.setText(""); Bitmap image1 = CodeUtils.createImage(textContent1, 400, 400, BitmapFactory.decodeResource(getResources(), R.mipmap.ic_launcher)); imgShow.setImageBitmap(image1); break; } }
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值