QR code and barcode scanning based on Google zxing, similar to WeChat QR code scanning

Source: Internet
Author: User
Tags drawtext getcolor gety

Reprinted please indicate the source: http://blog.csdn.net/xiaanming/article/details/10163203


I learned about the QR code. At that time, the QR code scanning function was launched, and I felt very novel. I scanned a picture and could add friends directly. It was incredible that I didn't know the QR code at that time, haha, when I was working on the project, the boss said that I would add the QR code scanning function, and then I went to Baidu, Google, and found that many of my friends had introduced the QR code scanning function, then I started the QR code scanning function with my introduction, followed by my post. Soon my project joined the QR code scanning function, and I was very happy.


With the advent of the QR code, the QR code is getting increasingly popular and can be seen everywhere, such as in the mall, KFC, restaurants, etc. For QR code scanning, we use Google's open-source framework zxing. We can go to ghost


Let's take a look at the project structure.

  • If you want to add this function to your project, you can directly. mining. app. zxing. camera, Com. mining. app. zxing. decoding, Com. mining. app. zxing. view these three packages are copied to your project, and then the corresponding resources are introduced. I also directly referenced them from my project, and the package name has not been changed, of course, you also need to reference zxing. jar

  • Com. example. the qr_codescan package contains a mipcaactivitycapture which directly introduces the code of my previous project. This activity mainly processes the scanning interface class, for example, the successful scanning of audio and vibration, etc, focus on handledecode (Result
    Result, bitmap barcode) method. After the scan is complete, the original parameters of the result and bitmap of the QR code are passed to handledecode (result, bitmap barcode, we only need to write the corresponding processing code in it, and do not need to change it elsewhere. Here I will process the scanning results and the photos taken by the scanning.

/*** Process scan result ** @ Param result * @ Param barcode */Public void handledecode (result, bitmap barcode) {inactivitytimer. onactivity (); playbeepsoundandvibrate (); string resultstring = result. gettext (); If (resultstring. equals ("") {toast. maketext (mipcaactivitycapture. this, "Scan failed! ", Toast. length_short ). show () ;}else {intent resultintent = new intent (); bundle = new bundle (); bundle. putstring ("result", resultstring); bundle. putparcelable ("bitmap", barcode); resultintent. putextras (bundle); this. setresult (result_ OK, resultintent);} mipcaactivitycapture. this. finish ();}

  • I made some changes to the layout of the mipcaactivitycapture interface. First, I used framelayout, Which is nested with relativelayout. The pictures in it are also taken out from it, I usually look for any picture I need. programmers in companies without art are hard-pressed.

The layout code is as follows:

<?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" />        <com.mining.app.zxing.view.ViewfinderView            android:id="@+id/viewfinder_view"            android:layout_width="wrap_content"            android:layout_height="wrap_content" />        <include            android:id="@+id/include1"            android:layout_width="fill_parent"            android:layout_height="wrap_content"            android:layout_alignParentTop="true"            layout="@layout/activity_title" />    </RelativeLayout></FrameLayout>

In this section, I will write the above part of the interface in another layout and include it in, because this activity_title is also used by other activities in my project. I also copied it directly.

<? XML version = "1.0" encoding = "UTF-8"?> <Relativelayout xmlns: Android = "http://schemas.android.com/apk/res/android" Android: layout_width = "fill_parent" Android: layout_height = "wrap_content" Android: Background = "@ drawable/mmtitle_bg_alpha"> <button Android: id = "@ + ID/button_back" Android: layout_width = "75.0dip" Android: text = "back" Android: Background = "@ drawable/mm_title_back_btn" Android: textcolor = "@ Android: color/White" Android: layout_height = "wrap_content" Android: layout_centervertical = "true" Android: layout_marginleft = "2dip"/> <textview Android: id = "@ + ID/textview_title" Android: layout_width = "wrap_content" Android: layout_height = "wrap_content" Android: layout_alignbaseline = "@ + ID/button_back" Android: layout_alignbottom = "@ + ID/button_back" Android: layout_centerhorizontal = "true" Android: gravity = "center_vertical" Android: text = "QR code scan" Android: textcolor = "@ Android: color/White "Android: textsize =" 18sp "/> </relativelayout>

  • In my demo, there is a main interface mainactivity, which contains a button, an imageview and a textview. click the button to enter the QR code scanning interface. When the scan is OK, return to the main interface, display the scan result to textview, and display the image to imageview. you can skip the process and add the image here. The layout of the main interface is as follows:
<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" Android: background = "# ffe1e0de"> <button Android: Id = "@ + ID/button1" Android: layout_width = "fill_parent" Android: layout_height = "wrap_content" Android: layout_alignparenttop = "true" Android: text = "Scan QR code"/> <textview Android: Id = "@ + ID/result" Android: layout_width = "fill_parent" Android: layout_height = "wrap_content" Android: layout_below = "@ + ID/button1" Android: lines = "2" Android: gravity = "center_horizontal" Android: textcolor = "@ Android: color/Black "Android: textsize =" 16sp "/> <imageview Android: Id =" @ + ID/qrcode_bitmap "Android: layout_width =" fill_parent "Android: layout_height = "fill_parent" Android: layout_alignparentleft = "true" Android: layout_below = "@ + ID/result"/> </relativelayout>
  • The code in mainactivity is as follows. The functions in mainactivity are described above.

Package COM. example. qr_codescan; import android. app. activity; import android. content. intent; import android. graphics. bitmap; import android. OS. bundle; import android. view. view; import android. view. view. onclicklistener; import android. widget. button; import android. widget. imageview; import android. widget. textview; public class mainactivity extends activity {private final static int scannin_grequest_code = 1;/*** display scan result */private textview mtextview; /*** display scanned image */private imageview mimageview; @ overrideprotected void oncreate (bundle savedinstancestate) {super. oncreate (savedinstancestate); setcontentview (R. layout. activity_main); mtextview = (textview) findviewbyid (R. id. result); mimageview = (imageview) findviewbyid (R. id. qrcode_bitmap); // click the button to jump to the QR code scanning interface. startactivityforresult is used to jump to the page. // After scanning, adjust it to the interface button mbutton = (button) findviewbyid (R. id. button1); mbutton. setonclicklistener (New onclicklistener () {@ overridepublic void onclick (view v) {intent = new intent (); intent. setclass (mainactivity. this, mipcaactivitycapture. class); intent. setflags (intent. flag_activity_clear_top); startactivityforresult (intent, scannin_grequest_code) ;}}@override protected void onactivityresult (INT requestcode, int resultcode, intent data) {super. onactivityresult (requestcode, resultcode, data); Switch (requestcode) {Case scannin_grequest_code: If (resultcode = result_ OK) {bundle = data. getextras (); // displays the scanned content of mtextview. settext (bundle. getstring ("result"); // display mimageview. setimagebitmap (Bitmap) data. getparcelableextra ("bitmap");} break ;}}}

  • The above code is relatively simple, but to make a scan box like that, the above Code does not have that effect, we must rewrite COM. mining. app. zxing. in the viewfinderview class under the View package, all the pictures are used. I drew them myself and the code comments are clear. Let's look at the Code directly. I believe you can understand it, if you want to modify the scan box size, go to the cameramanager class to modify

/** Copyright (c) 2008 zxing authors ** licensed under the Apache license, version 2.0 (the "License "); * You may not use this file before t in compliance with the license. * You may be obtain a copy of the license at ** http://www.apache.org/licenses/LICENSE-2.0 ** unless required by applicable law or agreed to in writing, software * distributed under the license is distributed on an "as is" basis, * Without warranties or conditions of any kind, either express or implied. * See the license for the specific language governing permissions and * limitations under the license. */package COM. mining. app. zxing. view; import Java. util. collection; import Java. util. hashset; import android. content. context; import android. content. res. resources; import android. graphics. bitmap; import android. graphics. canvas; Im Port android. graphics. color; import android. graphics. paint; import android. graphics. rect; import android. graphics. typeface; import android. util. attributeset; import android. view. view; import COM. example. qr_codescan.r; import COM. google. zxing. resultpoint; import COM. mining. app. zxing. camera. cameramanager;/*** this view is overlaid on top of the camera preview. it adds the viewfinder * rectangle and partial Transparency outside it, as well as the laser between * animation and result points. **/public final class viewfinderview extends view {Private Static final string tag = "log";/*** time to refresh the interface */Private Static final long animation_delay = 10l; private Static final int opaque = 0xff;/*** length of the four green corners */private int screenrate; /*** width of the four green corners */Private Static final int corner_width = 10;/*** middle of the scan box Line width */Private Static final int middle_line_width = 6;/*** gap between the middle line and the left and right sides of the scan box */Private Static final int middle_line_padding = 5; /*** the distance between the center line and the movement of each refresh */Private Static final int speen_distance = 5;/*** cell phone screen density */Private Static float density; /*** font size */Private Static final int text_size = 16;/*** font distance from the bottom of the scan box */Private Static final int text_padding_top = 30; /*** paint object reference */private paint ;/ * ** Top position of the intermediate slide line */private int slidetop;/*** bottom position of the intermediate slide line */private int slidebottom; private bitmap resultbitmap; private Final int maskcolor; private final int resultcolor; private final int resultpointcolor; private collection <resultpoint> possibleresultpoints; private collection <resultpoint> values; Boolean isfirst; Public viewfinderview (context, attributeset attrs) {super (con Text, attrs); density = context. getresources (). getdisplaymetrics (). density; // converts a pixel to dpscreenrate = (INT) (20 * density); paint = new paint (); resources Resources = getresources (); maskcolor = resources. getcolor (R. color. viewfinder_mask); resultcolor = resources. getcolor (R. color. result_view); resultpointcolor = resources. getcolor (R. color. possible_result_points); possibleresultpoints = new hashset <resultpoint> (5) ;}@ overridepublic void ondraw (canvas) {// scan box in the middle. Modify the size of the scan box and modify rect frame = cameramanager in cameramanager. get (). getframingrect (); If (frame = NULL) {return;} // initialize the top and bottom of the middle line sliding if (! Isfirst) {isfirst = true; slidetop = frame. top; slidebottom = frame. bottom;} // obtain the width and height of the screen. Int width = canvas. getwidth (); int Height = canvas. getheight (); paint. setcolor (resultbitmap! = NULL? Resultcolor: maskcolor); // draw the shadow part outside the scan box, which consists of four parts: the top of the scan box to the screen, bottom of the scan box to the bottom of the screen // left of the scan box to the left of the screen, the right of the scan box to the right of the screen 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 rectanglepaint. setalpha (opaque); canvas. drawbitmap (resultbitmap, frame. left, frame. top, paint);} else {// draw the corner on the side of the scan box. A total of 8 parts are painted. 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); CA Nvas. 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); CA Nvas. 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); // draw the middle line. Every time you refresh the interface, the middle line moves down speen_distanceslidetop ++ = 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); // paint the words in the scan box. setcolor (color. white); 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); collection <resultpoint> C Urrentpossible = 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 + poi NT. 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) ;}// only refresh the content of the scan box. Do not refresh postinvalidatedelayed (animation_delay, frame. left, frame. top, frame. right, frame. bottom) ;}} public void drawviewfinder () {resultbitmap = NULL; invalidate () ;}/ *** draw a bitmap with the result points highlighted instead of the live * scanning display. ** @ Param barcode * an image of the decoded barcode. */Public void drawresultbitmap (Bitmap barcode) {resultbitmap = barcode; invalidate ();} public void addpossibleresultpoint (resultpoint) {possibleresultpoints. add (point );}}

In the above Code, the middle line is used as an image, and I drew it here. If you want to simulate more, you can use the following code.

canvas.drawRect(frame.left + MIDDLE_LINE_PADDING, slideTop - MIDDLE_LINE_WIDTH/2, frame.right - MIDDLE_LINE_PADDING,slideTop + MIDDLE_LINE_WIDTH/2, paint);

Change

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

Find the scanning line, and I posted the distortion. Download the APK, change the suffix to zip, and decompress the package.

The font code under the image scan box needs to be modified so that the child can be automatically arranged in the middle according to the font. If the word is too long and I haven't processed it, you can handle it by yourself.

paint.setColor(Color.WHITE);  paint.setTextSize(TEXT_SIZE * density);  paint.setAlpha(0x40);  paint.setTypeface(Typeface.DEFAULT_BOLD); String text = getResources().getString(R.string.R.string.scan_text);float textWidth = paint.measureText(text);canvas.drawText(text, (width - textWidth)/2, (float) (frame.bottom + (float)TEXT_PADDING_TOP *density), paint)

Run the interface, where the green line in the middle will move up and down, which is similar to the effect. Of course, you still need the corresponding permissions to run it. If you are interested, you can download the demo.

I wrote this blog from and wrote it to the present. It seems to be a few words, but it actually takes a lot of time. If you think this article is helpful to you, let's talk about it. Haha, I have taken a bath and went to bed. I have not posted some resource files in the above project. If you want to see the results, you can download the source code.


Project source code, click to download

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.