二維碼的掃描與生成

二維碼呀,現(xiàn)在的項目基本都有的東西,早就有人寫出來了,我也是在用別人的基礎上寫寫心得啊什么的,自己封裝一個還沒那時間和技術去搞,所以這篇文章講的就是怎么用。


二維碼

呃,圖有點大,好像還暴露了些許信息,算了不管了,就這樣吧。

效果大概就是這樣的。

接下來講講怎么實現(xiàn)的:

首先是下包,用的是ZXing
http://download.csdn.net/download/wiseant/9136099
原諒我忘了之前自己用的是哪個,然后簡書又不能上傳,好了我百度了個版本一樣的發(fā)過來,我是用這個版本的,要是不行你們百度下這個版本吧,正常應該是OK的。

然后是布局文件,這個很簡單

<?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:id="@+id/activity_scan"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="#1c1c1c"
    android:orientation="vertical">

    <include layout="@layout/head"
        android:id="@+id/head"/>


    <SurfaceView                                                 //這個就是主要的啦
        android:id="@+id/surfaceview"
        android:background="@drawable/saomiao"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_below="@+id/head"/>



    <RelativeLayout                                                //這個本來不必要的,為了那天線沒辦法
        android:id="@+id/layout_contain"
        android:layout_width="match_parent"
        android:layout_height="180dp"
        android:layout_marginTop="170dp"
        android:layout_marginRight="70dp"
        android:layout_marginLeft="70dp">

        <com.***.**.view.*****//這個就是那條線
            android:id="@+id/scanline"
            android:layout_width="match_parent"
            android:layout_height="2dp"
            android:layout_marginTop="33dp"
            android:layout_alignParentLeft="true"
            android:layout_alignParentStart="true"/>

    </RelativeLayout>

    <TextView
        android:layout_width="match_parent"
        android:layout_height="180dp"
        android:textColor="@color/white"
        android:layout_gravity="bottom"
        android:gravity="center|top"
        android:padding="20dp"
        android:text="將醫(yī)生二維碼放入框內,即可自動掃描"
        android:layout_alignParentBottom="true"
        android:layout_alignParentLeft="true"
        android:layout_alignParentStart="true"/>

</RelativeLayout>

這里很多坑,SurfaceView 要是再嵌套一層layout的話,里面的畫面會變形,還有不能全屏(具體什么原因,暫時沒空去找,大神可以指點一下)。至于那個背景框,叫UI截個圖妥妥的不用自己話后面的線。
還有那個ScanLineView 是別人給我的,它的動畫長度略坑,所以勉強調成這樣剛好。
其實最好的方法就是改里面的代碼,但是時間不夠還是算了,將就著用吧。

接下來是activity的代碼了,沒有全部貼,二維碼那塊都在這里了,其實很少東西的

   @Override
    public void onCreate(Bundle icicle) {
        super.onCreate(icicle);

//        setContentView(R.layout.activity_scan);
        title.setText("掃描醫(yī)生二維碼");

        qrScanManager = new QRScanManager(this);           //主要是這玩意而已
        layout_contain = (RelativeLayout) findViewById(R.id.layout_contain);
        qrScanManager.initWithSurfaceView(this, R.id.surfaceview);
        qrScanManager.setBeepResource(R.raw.beep);
        Rect rect = initCrop();
        qrScanManager.setCropRect(rect);

        ScanLineView scanline = (ScanLineView) findViewById(R.id.scanline);

        // 動畫效果
        TranslateAnimation animation = new TranslateAnimation(
                Animation.RELATIVE_TO_PARENT, 0.0f,
                Animation.RELATIVE_TO_PARENT, 0.0f,
                Animation.RELATIVE_TO_PARENT, 0.0f,
                Animation.RELATIVE_TO_PARENT, 1.0f);
        animation.setDuration(4500);
        animation.setRepeatCount(-1);
        animation.setRepeatMode(Animation.RESTART);
        scanline.startAnimation(animation);
    }

    private Rect initCrop() {

        int screenWidth = getWindowManager().getDefaultDisplay().getWidth();

        RelativeLayout.LayoutParams params = (RelativeLayout.LayoutParams) layout_contain.getLayoutParams();
        int x = params.leftMargin;
        int y = params.topMargin;
        int width = screenWidth - 2 * x;
        int height = width;

        params.height = height;

        layout_contain.setLayoutParams(params);

        return new Rect(x, y, width + x, height + y);
    }

    @Override
    protected void onResume() {
        // TODO Auto-generated method stub
        super.onResume();

        qrScanManager.onResume();

    }

    @Override
    protected void onPause() {
        qrScanManager.onPause();
        super.onPause();
    }

    @Override
    protected void onDestroy() {
        qrScanManager.onDestroy();
        super.onDestroy();
    }

    @Override
    public void onScanResult(String content) {
      Toast.makeText(this, "結果:" + code[1], Toast.LENGTH_SHORT).show();
    }

至于那個ScanLineView 其實要是不要求的話去掉它,代碼就簡單多了,要的人我放上代碼吧


public class ScanLineView extends View {
    Paint paint = new Paint();

    private float density;// 屏幕密度
    private float width, height;// 控件的寬度高度

    public ScanLineView(Context context) {
        super(context);
        init();
    }

    @TargetApi(Build.VERSION_CODES.LOLLIPOP)
    public ScanLineView(Context context, AttributeSet attrs, int defStyleAttr,
                        int defStyleRes) {
        super(context, attrs, defStyleAttr, defStyleRes);
        init();
    }

    public ScanLineView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init();
    }

    public ScanLineView(Context context, AttributeSet attrs) {
        super(context, attrs);
        init();
    }

    private void init() {
        density = getResources().getDisplayMetrics().density;
        // 去鋸齒
        paint.setAntiAlias(true);
        paint.setColor(Color.parseColor("#53d555"));

        
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        int widthMode = MeasureSpec.getMode(widthMeasureSpec);
        int widthSize = MeasureSpec.getSize(widthMeasureSpec);
        int heightMode = MeasureSpec.getMode(heightMeasureSpec);
        int heightSize = MeasureSpec.getSize(heightMeasureSpec);

        if (widthMode == MeasureSpec.EXACTLY) {
            width = widthSize;

        } else {
            width = (int) (250 * density);
        }

        if (heightMode == MeasureSpec.EXACTLY) {
            height = heightSize;

        } else {
            height = (int) (250 * density);
        }

        // Log.e("tag", " ------ width:"+width +"   height:"+height);
        setMeasuredDimension((int) this.width, (int) this.height);
        
        Shader mShader = new LinearGradient( width/2.0f,height,width/2.0f, 0, new int[] {
                Color.BLUE, Color.TRANSPARENT}, null,
                Shader.TileMode.CLAMP);
        paint.setShader(mShader);
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);

        // 為Paint設置漸變器

        // 繪制矩形
        canvas.drawRect(0, 0, width, height, paint);
    }
}

嗯,就是這個自定義View了,其實代碼很少,東西也不多

掃描的就是這么簡單就搞定了···

然后是生成二維碼,這個更簡單,一個工具類搞定

    /**
     * 生成一個二維碼圖像
     *
     * @param url
     *          傳入的字符串,通常是一個URL
     * @param QR_WIDTH
     *          寬度(像素值px)
     * @param QR_HEIGHT
     *          高度(像素值px)
     * @return
     */
    public static final Bitmap create2DCoderBitmap(String url, int QR_WIDTH, int QR_HEIGHT) {
        try {
            // 判斷URL合法性
            if (url == null || "".equals(url) || url.length() < 1) {
                return null;
            }
            Hashtable<EncodeHintType, String> hints = new Hashtable<EncodeHintType, String>();
            hints.put(EncodeHintType.CHARACTER_SET, "utf-8");
            // 圖像數(shù)據轉換,使用了矩陣轉換
            BitMatrix bitMatrix = new QRCodeWriter().encode(url, BarcodeFormat.QR_CODE, QR_WIDTH, QR_HEIGHT, hints);
            int[] pixels = new int[QR_WIDTH * QR_HEIGHT];
            // 下面這里按照二維碼的算法,逐個生成二維碼的圖片,
            // 兩個for循環(huán)是圖片橫列掃描的結果
            for (int y = 0; y < QR_HEIGHT; y++) {
                for (int x = 0; x < QR_WIDTH; x++) {
                    if (bitMatrix.get(x, y)) {
                        pixels[y * QR_WIDTH + x] = 0xff000000;
                    } else {
                        pixels[y * QR_WIDTH + x] = 0xffffffff;
                    }
                }
            }
            // 生成二維碼圖片的格式,使用ARGB_8888
            Bitmap bitmap = Bitmap.createBitmap(QR_WIDTH, QR_HEIGHT, Bitmap.Config.ARGB_8888);
            bitmap.setPixels(pixels, 0, QR_WIDTH, 0, 0, QR_WIDTH, QR_HEIGHT);
            // 顯示到一個ImageView上面
            // sweepIV.setImageBitmap(bitmap);
            return bitmap;
        } catch (WriterException e) {
            Log.i("log", "生成二維碼錯誤" + e.getMessage());
            return null;
        }
    }

生成二維碼,一個bitmap搞定
Bitmap bitmap = QRCodeUtil.create2DCoderBitmap(qrCodeBean.getQRCodeUrl(), 250, 250);

有了bitmap,然后愛放哪放哪,妥妥的就這么簡單搞定了。

說說題外話:
最近少寫了好多篇文章了,說是項目多了,忙不過來,其實還有原因就是自己懶,天氣冷了,人也越變越懶了,本來這篇文章早幾天就想寫的了,拖啊拖啊的就到了今天。

話說,最近逛著逛著簡書,發(fā)現(xiàn)喜歡上了看 堂主姓蔡 這個人寫的故事,大多是鬼故事,都還不錯的樣子。

再有,今晚準備剁手

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
【社區(qū)內容提示】社區(qū)部分內容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內容

友情鏈接更多精彩內容