Android進階之路 - 截取View爲圖片

此篇文章都來源於項目需求 - -

起由:因需分享圖片到微信、QQ等三方平臺 ; 同時不可展現View在當前分享一級視圖內;
解決方式:使用相對佈局進行佈局覆蓋,需要分享的View設置爲Invisible狀態,點擊分享時截取View轉爲圖片,然後進行分享

Effect :
在這裏插入圖片描述

注意 :

  • 雖然已經工作了很久,我依舊喜歡複雜的事情簡單化~ 能直接Copy的決不自己寫~能寫一行的代碼絕不寫倆行(內心獨白:畢竟我還要去學更多的東西嘛 ~ ~)
  • 所截View,按理不應展示在一級視圖內!但是爲了效果,故進行了顯示;
  • 在我的真實項目場景中,所截View我們需要設置 android:visibility=“invisible” ,這樣既在一級表現頁進行了展示,又不會報出空指針
  • 因爲只是截取View變成圖片進行分享,並沒有保存在本地,所以不需要申請權限!
  • 最後有一些擴展方法,包含圖片壓縮、保存圖片、友盟分享使用

特別注意:

因爲我截取View轉爲Bitmap主要作用於三方分享!

但是QQ分享時多次點擊,多次無效 ;

經過Debug查看後~

首先發現原因是bitmap返回爲null

然後我用了文章末尾的擴展方法(大多都是返回爲null,使用緩存處理)
但是根本無效!!!

然後耗費了一下午時間,我發現QQ分享竟然要申請存儲權限!竟然要申請存儲權限!竟然要申請存儲權限!

好吧, 哥們或許你截取View轉bitmap並不是爲空!因爲View傳入之後Debug發現是可以獲取圖片的,只是到了return的時候發現bitmap爲空!!!

代碼部分

Demo代碼(Demo下載

  • MainActivity
package com.example.viewtobitmap;

import android.app.Activity;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.os.Bundle;
import android.view.Display;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.ImageView;
import android.widget.LinearLayout;

/**
 * @author Mr.Liu
 * */
public class MainActivity extends Activity {
    private LinearLayout tempview;
    private ImageView mView;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        //我們要截取的View
        tempview = (LinearLayout) findViewById(R.id.gone_view);
        //用於展示我們已截取View的承載視圖
        mView = (ImageView) findViewById(R.id.img);

        //點擊事件
        findViewById(R.id.changeviewtobitmap).setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View v) {
                //屏幕參數
                //Display disPlay = getWindowManager().getDefaultDisplay();
                mView.setImageBitmap(convertViewToBitmap(tempview, null));
            }
        });
    }

    /**
     * 主要方法:創建一個bitmap放於畫布之上進行繪製 (簡直如有神助)
     */
    private static Bitmap convertViewToBitmap(View tempView, Display disPlay) {
        Bitmap bitmap = Bitmap.createBitmap(tempView.getWidth(),
                tempView.getHeight(), Bitmap.Config.ARGB_8888);
        Canvas canvas = new Canvas(bitmap);
        tempView.draw(canvas);
        return bitmap;
    }
}

  • MainActivity Xml
<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:background="#ffffff"
              android:orientation="vertical">

    <LinearLayout
        android:id="@+id/gone_view"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:background="#ff0"
        android:orientation="vertical"
        android:paddingBottom="10dp"
        android:visibility="visible">

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="center"
            android:layout_marginTop="10dp"
            android:text="你是我患得患失的夢,我是你可有可無的人~~"/>

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="center"
            android:layout_marginTop="10dp"
            android:text="畢竟這穿越山河的箭,刺的都是用情致疾的人~~"/>

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="center"
            android:layout_marginTop="10dp"
            android:text="畢竟這穿越山河的箭,刺的都是用情致疾的人~~"/>

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="center"
            android:layout_marginTop="10dp"
            android:text="就讓這牽腸掛肚的酒,硫酸一樣刺激在你我的心頭~~"/>
    </LinearLayout>

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginTop="50dp"
        android:gravity="center"
        android:orientation="vertical"
        android:padding="4dp">

        <Button
            android:id="@+id/changeviewtobitmap"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="截View視圖"/>
    </LinearLayout>

    <ImageView
        android:id="@+id/img"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        />
</LinearLayout>

項目代碼(主要是QQ分享,所以只貼出關鍵部分!這是文中我用到的權限申請

	RxPermissions rxPermissions = new RxPermissions(this);
                //Manifest.permission.WRITE_EXTERNAL_STORAGE, Manifest.permission.CAMERA 文件存儲權限、相機權限
                rxPermissions.request(Manifest.permission.WRITE_EXTERNAL_STORAGE, 		Manifest.permission.CAMERA).subscribe(new Observer<Boolean>() {
                    @Override
                    public void onSubscribe(Disposable d) {

                    }

                    @Override
                    public void onNext(Boolean aBoolean) {
                        //有權限的狀態
                        if (aBoolean) {
                            Display displayQQ = getWindowManager().getDefaultDisplay();
                            UMImage umImageQQ = new UMImage(InviteAwardActivity.this, convertViewToBitmap(mSharePicture, displayQQ));
                           /* 便於找到自身錯誤
                            if (thumbImage == null) {
                                ToastUtils.shortShow("分享圖片爲空");
                            }*/
                            umImageQQ.setThumb(umImageQQ);
                            boolean qqClientAvailable = PlatformUtil.isQQClientAvailable(InviteAwardActivity.this);
                            if (qqClientAvailable) {
                                new ShareAction(InviteAwardActivity.this)
                                        .setPlatform(SHARE_MEDIA.QQ)
                                        .withMedia(umImageQQ)
                                        .setCallback(new UMShareListener() {
                                            @Override
                                            public void onStart(SHARE_MEDIA shareMedia) {

                                            }

                                            @Override
                                            public void onResult(SHARE_MEDIA shareMedia) {
                                                ToastUtils.shortShow("分享成功!");
                                            }

                                            @Override
                                            public void onError(SHARE_MEDIA shareMedia, Throwable throwable) {

                                            }

                                            @Override
                                            public void onCancel(SHARE_MEDIA shareMedia) {

                                            }
                                        }).share();
                            } else {
                                ToastUtils.shortShow("請安裝QQ客戶端");
                            }
                        }
                        //無權限的狀態
                        else {
                            Toast.makeText(InviteAwardActivity.this, getString(R.string.picture_jurisdiction), Toast.LENGTH_SHORT).show();
                        }
                    }

                    @Override
                    public void onError(Throwable e) {

                    }

                    @Override
                    public void onComplete() {

                    }
                });
        

擴展方法

以下內容 : 我認爲可以先行忽略,不過也可以看看,畢竟是看了十幾篇類似博文的產物 ~

方式一 :

  • 圖片壓縮、View轉換
 /**
     * 壓縮圖片
     *
     * @param bgimage
     * @param newWidth
     * @param newHeight
     * @return
     */
    public static Bitmap zoomImage(Bitmap bgimage, double newWidth, double newHeight) {
        // 獲取這個圖片的寬和高
        float width = bgimage.getWidth();
        float height = bgimage.getHeight();
        // 創建操作圖片用的matrix對象
        Matrix matrix = new Matrix();
        // 計算寬高縮放率
        float scaleWidth = ((float) newWidth) / width;
        float scaleHeight = ((float) newHeight) / height;
        // 縮放圖片動作
        //matrix.postScale(scaleWidth, scaleHeight);//TODO 因爲寬高不確定的因素,所以不縮放
        Bitmap bitmap = Bitmap.createBitmap(bgimage, 0, 0, (int) width,
                (int) height, matrix, true);
        return bitmap;
    }

	/**
     * 截取指定View爲圖片
     *
     * @param view
     * @return
     * @throws Throwable
     */
    public static Bitmap captureView(View view) throws Throwable {
        Bitmap bm = Bitmap.createBitmap(view.getWidth(), view.getHeight(), Bitmap.Config.ARGB_8888);
        view.draw(new Canvas(bm));
        return bm;
    }

壓縮使用

	
	 	Bitmap bitmap = null;
          try {
                 bitmap = captureView(mShareBackgroundSign);
              } catch (Throwable throwable) {
                    throwable.printStackTrace();
              }
           //圖片壓縮,加快使用速度~
           zoomImage(bitmap, 720, 1280);

  • 圖片保存到本地 (若要保存,務必記得權限申請)
public static void savePhotoToSDCard(Bitmap photoBitmap, String path, String photoName) {
        if (checkSDCardAvailable()) {
            File dir = new File(path);
            if (!dir.exists()) {
                dir.mkdirs();
            }
 
            File photoFile = new File(path, photoName + ".png");
            FileOutputStream fileOutputStream = null;
            try {
                fileOutputStream = new FileOutputStream(photoFile);
                if (photoBitmap != null) {
                    if (photoBitmap.compress(Bitmap.CompressFormat.PNG, 100, fileOutputStream)) {
                        fileOutputStream.flush();
                    }
                }
            } catch (FileNotFoundException e) {
                photoFile.delete();
                e.printStackTrace();
            } catch (IOException e) {
                photoFile.delete();
                e.printStackTrace();
            } finally {
                try {
                    fileOutputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

方式二 (有人說截取view轉bitmap後爲null~ 用這種方式清理緩存) :

    public static Bitmap getViewBp(View v) {
        if (null == v) {
            return null;
        }
        v.setDrawingCacheEnabled(true);
        v.buildDrawingCache();
        if (Build.VERSION.SDK_INT >= 11) {
            v.measure(View.MeasureSpec.makeMeasureSpec(v.getWidth(),
                    View.MeasureSpec.EXACTLY), View.MeasureSpec.makeMeasureSpec(
                    v.getHeight(), View.MeasureSpec.EXACTLY));
            v.layout((int) v.getX(), (int) v.getY(),
                    (int) v.getX() + v.getMeasuredWidth(),
                    (int) v.getY() + v.getMeasuredHeight());
        } else {
            v.measure(View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED),
                    View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED));
            v.layout(0, 0, v.getMeasuredWidth(), v.getMeasuredHeight());
        }
        Bitmap b = Bitmap.createBitmap(v.getDrawingCache(), 0, 0, v.getMeasuredWidth(), v.getMeasuredHeight());

        v.setDrawingCacheEnabled(false);
        v.destroyDrawingCache();
        return b;
    }

方式三 (有人說截取view轉bitmap後爲null~ 用這種方式清理緩存):

	public static Bitmap convertViewToBitmap(View view) {
        view.setDrawingCacheEnabled(true);
        view.measure(View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED), View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED));
        view.layout(0, 0, view.getMeasuredWidth(), view.getMeasuredHeight());
        view.buildDrawingCache();
        Bitmap bitmap = view.getDrawingCache();
        view.setDrawingCacheEnabled(false);
        return bitmap;
 }
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章