最近的安卓開發中遇到了一個看起來比較棘手的問題:三方分享圖片,剛開始的需求僅僅是分享(動漫圖片類app)畫作主圖,使用的是友盟的。友盟支持純圖片分享,要提供一個bitmap
<span style="white-space:pre"> </span>UMImage img = new UMImage(context, bmp);
//設置微信好友分享內容
WeiXinShareContent weixinContent = new WeiXinShareContent();
//設置分享圖片
weixinContent.setShareImage(img);
mController.setShareMedia(weixinContent);
//設置微信朋友圈分享內容
CircleShareContent circleMedia = new CircleShareContent();
//設置朋友圈title
circleMedia.setTitle(title);
circleMedia.setShareImage(img);
mController.setShareMedia(circleMedia);
剛開始沒什麼問題。
之後,產品把需求改了,需要在畫作主圖中添加水印表明畫師頭像,畫師名,畫作描述,以及相應的app二維碼圖片;
由於這個功能ios最先開始做,我就向ios取經。而ios那邊的做法是使用view轉bitmap,於是到網上查找相應的資料
方案一:ios的方案
private Bitmap getShareBitmap() {
View headerView = LayoutInflater.from(mActivity).inflate(
R.layout.fragment_share, null);
SimpleDraweeView img_user = (SimpleDraweeView)headerView.findViewById(R.id.img_user);
TextView comic_name = (TextView)headerView.findViewById(R.id.comic_name);
TextView comic_title = (TextView)headerView.findViewById(R.id.comic_title);
FrescoHelper.displayImage2Cir(img_user, resp.data.avatar, true);
comic_title.setText(resp.data.content);
comic_name.setText(resp.data.nickname);
int name_height = getFontHeight(DisplayUtils.sp2px(getActivity(),18.0f));
int title_height = getFontHeight(DisplayUtils.sp2px(getActivity(),16.0f));
int bottom_height = getFontHeight(DisplayUtils.sp2px(getActivity(),14.0f));
int viewHight = name_height+title_height*2+bottom_height+96+50;
return BitmapUtils.getViewBitmap(headerView,(int)StringUtils.getScreenWidth(),viewHight);
}
/**
* 把View繪製到Bitmap上
* @param view 需要繪製的View
* @param width 該View的寬度
* @param height 該View的高度
* @return 返回Bitmap對象
*/
public static Bitmap getViewBitmap(View view, int width, int height) {
Bitmap bitmap = null;
if (view != null) {
view.clearFocus();
view.setPressed(false);
boolean willNotCache = view.willNotCacheDrawing();
view.setWillNotCacheDrawing(false);
int color = view.getDrawingCacheBackgroundColor();
view.setDrawingCacheBackgroundColor(0);
float alpha = view.getAlpha();
view.setAlpha(1.0f);
if (color != 0) {
view.destroyDrawingCache();
}
int widthSpec = View.MeasureSpec.makeMeasureSpec(width, View.MeasureSpec.EXACTLY);
int heightSpec = View.MeasureSpec.makeMeasureSpec(height, View.MeasureSpec.EXACTLY);
view.measure(widthSpec, heightSpec);
view.layout(0, 0, width, height);
view.buildDrawingCache();
Bitmap cacheBitmap = view.getDrawingCache();
if (cacheBitmap == null) {
Log.e("view.ProcessImageToBlur", "failed getViewBitmap(" + view + ")",
new RuntimeException());
return null;
}
bitmap = Bitmap.createBitmap(cacheBitmap);
cacheBitmap.recycle();
cacheBitmap = null;
view.setAlpha(alpha);
view.destroyDrawingCache();
view.setWillNotCacheDrawing(willNotCache);
view.setDrawingCacheBackgroundColor(color);
}
return bitmap;
}
headerView是一個自己佈局的linerLayout形式
這樣看起來是沒什麼問題,一測試對於特別的長圖(畫作主圖個別存在高度是寬度的10倍)會帶導致OOM,方案一捨棄
方案二:自定義拼接bitmap
這個方案需要縮放,否則可能會OOM,縮放分畫師主圖縮放和底部描述縮放兩種
主圖縮放主要是爲了對應長圖,地圖縮放主要是對應於高度不高的短圖,直接上代碼拼接代碼那塊就不貼出來了
private Bitmap createShareBitmap(Bitmap topBtp,Bitmap btnBtp) {
if (null ==topBtp ||null==btnBtp) {
Logger.d("src == null");
return null;
}
//頭部的測量寬高
int topWid = topBtp.getWidth(),topHig = topBtp.getHeight();
int totalWid,totalHig;
//底部的測量寬高
int btnWid = btnBtp.getWidth(),btnhig = btnBtp.getHeight();
//整體的btn設置
Bitmap allBtp;
if(topBtp.getHeight()>2000){
//頭部的高度大於2K,即爲長圖,縮放底部的Bitmap,保持頭部寬度不變,長圖,高度計算
totalWid = topWid;
//縮放底部
Matrix matrix = new Matrix();
float scale = (float) topWid / btnWid;
matrix.postScale(scale, scale);
//縮放後的底部數據
Bitmap btnScaleBtp = Bitmap.createBitmap(btnBtp, 0, 0, btnWid, btnhig, matrix, true);
//總體的高度=縮放後底部高度+頭部高度
totalHig =topHig+btnScaleBtp.getHeight();
// 創建位圖
allBtp = Bitmap.createBitmap(totalWid, totalHig, Bitmap.Config.RGB_565);
Logger.d("totalWid="+totalWid+"totalHig="+totalHig);
// 創建一個新的和SRC長度寬度一樣的位圖
Canvas cv = new Canvas(allBtp);
// 畫底層圖
cv.drawBitmap(topBtp, 0, 0, null);// 在 0,0座標開始畫入src
// 畫水印
cv.drawBitmap(btnScaleBtp, 0, topHig, null);// 在src的右下角畫入水印
// 保存位圖
cv.save(Canvas.ALL_SAVE_FLAG);// 保存
cv.restore();// 存儲
recycleBitmap(btnScaleBtp);
return allBtp;
}else{
//頭部的高度小於2K,即爲一般圖,縮放頭部的Bitmap,保持底部寬度不變即屏幕寬度
totalWid = btnWid;
//縮放頭部
Matrix matrix = new Matrix();
float scale = (float) totalWid / topWid;
matrix.postScale(scale, scale);
//縮放後的底部數據
Bitmap topScaleBtn = Bitmap.createBitmap(topBtp, 0, 0, topWid, topHig, matrix, true);
//總體的高度=縮放後頭部高度+底部高度
totalHig =btnhig+topScaleBtn.getHeight();
// 創建位圖
allBtp = Bitmap.createBitmap(totalWid, totalHig, Bitmap.Config.RGB_565);
Logger.d("totalHig="+totalHig+"totalWid="+totalWid);
// 創建一個新的和SRC長度寬度一樣的位圖
Canvas cv = new Canvas(allBtp);
// 畫底層圖
cv.drawBitmap(topScaleBtn, 0, 0, null);// 在 0,0座標開始畫入src
// 畫水印
cv.drawBitmap(btnBtp, 0, topScaleBtn.getHeight(), null);// 在src的右下角畫入水印
// 保存位圖
cv.save(Canvas.ALL_SAVE_FLAG);// 保存
cv.restore();// 存儲
recycleBitmap(topScaleBtn);
return allBtp;
}
}
暫時是解決問題了,但是感覺繁瑣
方案三:Scrollview截圖
一次無意間查看到關於android截屏的知識,看到關於截取超過屏幕的圖片方法,其中一個ScrollView的截圖方式
很簡單,也分享給大家
/**
* 截取scrollview的屏幕
* @param scrollView
* @return
*/
public static Bitmap getBitmapByView(ScrollView scrollView) {
int h = 0;
Bitmap bitmap = null;
// 獲取scrollview實際高度
for (int i = 0; i < scrollView.getChildCount(); i++) {
h += scrollView.getChildAt(i).getHeight();
scrollView.getChildAt(i).setBackgroundColor(
Color.parseColor("#ffffff"));
}
// 創建對應大小的bitmap
bitmap = Bitmap.createBitmap(scrollView.getWidth(), h,
Bitmap.Config.RGB_565);
final Canvas canvas = new Canvas(bitmap);
scrollView.draw(canvas);
return bitmap;
}
ScrollView截屏來源於:點擊打開鏈接