最近的安卓开发中遇到了一个看起来比较棘手的问题:三方分享图片,刚开始的需求仅仅是分享(动漫图片类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截屏来源于:点击打开链接