此篇文章都來源於項目需求 - -
起由:因需分享圖片到微信、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;
}