1. 程式人生 > >Android 動態載入二維碼檢視生成快照

Android 動態載入二維碼檢視生成快照

1.需求背景

需要實現一個動態載入但不顯示出來的檢視,且該檢視上有個動態生成的二維碼,最後用其去生成一張快照(也就是圖片)。

(常見這種情況是來源於“圖片分享”的功能需求,與普通圖片分享不同在於,該快照圖片是動態載入不顯示的。)


2.需求功能拆解

  • 動態二維碼的實現
  • 動態檢視生成快照的實現

3.踩坑點提要

  • 獲取不到動態檢視的bitmap
  • 無法獲取最新動態檢視的bitmap

4.開發實現

動態載入的檢視的佈局檔案程式碼:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:id="@+id/qrcodeContentLl"
    android:background="#F0E68C"
    android:orientation="vertical">

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center"
        android:layout_marginTop="100dp"
        android:text="二維碼快照"
        android:textSize="18sp"
        android:textStyle="italic" />

    <ImageView
        android:id="@+id/qrcodeIv"
        android:layout_width="100dp"
        android:layout_height="100dp"
        android:layout_gravity="center"
        android:layout_marginTop="@dimen/activity_vertical_margin"
        android:scaleType="fitCenter" />

    <!--<TextView-->
        <!--android:layout_width="wrap_content"-->
        <!--android:layout_height="wrap_content"-->
        <!--android:layout_marginTop="800dp"-->
        <!--android:text="ahahds"-->
        <!--android:layout_gravity="center"/>-->
</LinearLayout>

大概樣式如下:


(上面的線框是用來顯示動態生成的二維碼圖片的)

a.動態二維碼的實現

關於這塊內容,網上有太多例子了,其實也不用詳解。主要是利用Zxing提供的jar包來進行處理。需要看這塊的詳細程式碼可以去文章最後提供的GitHub地址檢視,在此只提供下該jar包的資源下載(專案中若只涉及生成二維碼模組,那麼只要core核心jar包即可):點選下載>> core-3.3.0.jar 

b.動態檢視生成快照的實現

  private void inflateAndShowCaptureView() {
        if (hideView == null) {
            hideView = LayoutInflater.from(this).inflate(R.layout.layout_quick_capture, null);
            qrcodeIv = (ImageView) hideView.findViewById(R.id.qrcodeIv);
            hideView.setDrawingCacheEnabled(true);//設定控制元件允許繪製快取
            hideView.measure(View.MeasureSpec.makeMeasureSpec(mainLayoutLl.getWidth(), View.MeasureSpec.EXACTLY),
                    View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED));
            hideView.layout(0, 0, hideView.getMeasuredWidth(), hideView.getMeasuredHeight());
        } else {
            hideView.destroyDrawingCache();//要得到新的檢視,就得銷燬之前的快取
        }

        showCaptureView();
    }

    private void showCaptureView() {
        String content = contentEt.getText().toString().trim();
        if (content == null || content.length() == 0) {
            return;
        }
        if (qrcodeIv.getWidth() == 0) {
            return;
        }
        Bitmap qrcodeBitmap = ZXingUtils.createQRImage(content, qrcodeIv.getWidth(), qrcodeIv.getHeight());
        qrcodeIv.setImageBitmap(qrcodeBitmap);//先將生成的二維碼顯示在載入的檢視上

        Bitmap bitmap = hideView.getDrawingCache();  // 獲取檢視的繪製快取(快照)
        if (bitmap != null) {
            showIv.setImageBitmap(bitmap);
        }

    }

1.首先獲取到檢視的bitmap是通過getDrawingCache()得到的。

  • 若檢視是在介面上直接顯示出來的——>那麼使用該方法直接獲取bitmap是沒有問題的;
  • 若檢視是動態載入且不顯示出來,那麼此時獲取bitmap是null。

此處的解決辦法就是手動給該檢視佈局:

            hideView.measure(View.MeasureSpec.makeMeasureSpec(mainLayoutLl.getWidth(), View.MeasureSpec.EXACTLY),
                    View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED));
            hideView.layout(0, 0, hideView.getMeasuredWidth(), hideView.getMeasuredHeight());
有關於以上兩種方法的使用,可以參考這個文件的解釋:點選檢視>>

當然,篇幅有點長,以下做點簡單解釋:

View.MeasureSpec.makeMeasureSpec(int size , int mode)中有兩個引數,size和mode,第一組MeasureSpec中我將size設定為了當前顯示頁面的佈局的寬度(也就是螢幕寬度),然後mode設定為EXACTLY——>所表示的意義是:給hideView中的子View指定了精確的寬度大小為當前螢幕的寬度。

mode有三種,EXACTLY,AT_MOST,UNSPECIFIED。在上面程式碼中,將高度的size指定為0,mode指定為 UNSPECIFIED 則表示——>整個動態載入的檢視高度指定為:依據於最後子View確認的高度。

若將第一組MeasureSpec的相關引數也改為size = 0, mode = UNSPECIFIED,則兩組圖對比顯示如下:


可以看到,動態生成的快照的寬度也變成了顯示二維碼的ImageView的寬度了。

擴充套件:如何在寬高均為size = 0 && mode= UNSPECIFIED 的情況下獲取整個螢幕大小的檢視呢?

——>用幾個隱藏的元件埋在檢視的四個邊界,啊哈哈哈哈哈!

2.通過destroyDrawingCache()來刪除之前的快取。