在做项目的时候,产品提出了一个需求就是分享图片到微信或者朋友圈。乍一眼看到这个需求,觉得so easy呀,第三方都提供了对应的API并且自己也封装好了的。谁知道真正在做的时候一堆问题,本来1个小时应该搞定的需要害我整整搞了两天。算了,废话不多说了,直接上代码。
注意:我要分享出去的图在界面上不可见,同时要自己加上二维码和一些文字说明
在提供解决方案前,我先贴几个实现其他功能的代码作为笔记
实现截屏(当前屏幕):
/**
* @return 截图
*/
public static Bitmap getBitmap(Activity activity) {
int width = activity.getWindow().getDecorView().getRootView().getWidth();
int height = activity.getWindow().getDecorView().getRootView().getHeight();
View view = activity.getWindow().getDecorView().getRootView();
view.setDrawingCacheEnabled(false);
view.buildDrawingCache();
Bitmap temBitmap = view.getDrawingCache();
Bitmap bitmap = Bitmap.createBitmap(temBitmap, 0, 0, width, height);
view.destroyDrawingCache();//不清空,第二次截屏则使用的是缓存的同一张。
return Util.cropBitmap(bitmap, FontUtil.dip2px(activity, 44f) + Util.getStatusHeight(activity), FontUtil.dip2px(activity, 49f));
}
[点击并拖拽以移动]
实现View截图(View可见):
/**
* 把View绘制到Bitmap上
*
* @return 返回Bitmap对象
*/
public static Bitmap getPostViewBitmap(View v) {
v.clearFocus();
v.setPressed(false);
boolean willNotCache = v.willNotCacheDrawing();
v.setWillNotCacheDrawing(false);
int color = v.getDrawingCacheBackgroundColor();
v.setDrawingCacheBackgroundColor(0);
if (color != 0) {
v.destroyDrawingCache();
}
v.buildDrawingCache();
Bitmap cacheBitmap = v.getDrawingCache();
if (cacheBitmap == null) {
return null;
}
Bitmap bitmap = Bitmap.createBitmap(cacheBitmap);
v.destroyDrawingCache();
v.setWillNotCacheDrawing(willNotCache);
v.setDrawingCacheBackgroundColor(color);
return bitmap;
}
实现View截图(View不可见):
在实现这个的时候比较坑,在网上搜到的大部分都是我上面的第二种,但是大部分的人都不会告诉你截图成功的前提是该View是可见的。导致我在实现这个功能的时候获取到的bitmap永远是空
实现这个功能要分几个步骤:
1.测量View的宽高
private static void layoutView(View v, int width, int height) {
v.layout(0, 0, width, height);
int measuredWidth = View.MeasureSpec.makeMeasureSpec(width, View.MeasureSpec.EXACTLY);
int measuredHeight = View.MeasureSpec.makeMeasureSpec(height, View.MeasureSpec.AT_MOST);
v.measure(measuredWidth, measuredHeight);
v.layout(0, 0, v.getMeasuredWidth(), v.getMeasuredHeight());
}
2.加载View的内容数据
3.生成bitmap
public static void getBitmap(View v, String rmb, int height) {
int measuredWidth = v.getWidth();
int measuredHeight = height;
if (measuredWidth > 0) {
Bitmap bmp = Bitmap.createBitmap(measuredWidth, measuredHeight, Bitmap.Config.ARGB_8888);
Canvas c = new Canvas(bmp);
c.drawColor(Color.WHITE);
v.layout(0, 0, measuredWidth, measuredHeight);
v.draw(c);
new PostShare(v.getContext(), null, null, null, PostShare.ShareType.IMAGE, 1, bmp).share(SHARE_MEDIA.WEIXIN_CIRCLE);
}
}
注意,最好是先测量再填充数据。
回到前头,我在做的时候,条件性的把显示区域用ImageView来显示,结果图片是显示出来的,但是图片由于太长,导致宽度无法与下面的自己填充的内容进行适配,所以这个方案最后被pass掉了,最后我采用Webview来进行处理,因为Webvie可以自适应屏幕大小,所以不存在适配的问题。
public static void shareFictionBitmap(Context context, String bkH5, String title, String content, String webUrl, String qrUrl, String rmb) {
MyToast.showCenterSortToast(context, "图片生成中");
DisplayMetrics metric = new DisplayMetrics();
((Activity) context).getWindowManager().getDefaultDisplay().getMetrics(metric);
int width = metric.widthPixels;// 屏幕宽度(像素)
View view = LayoutInflater.from(context).inflate(R.layout.share_fiction, null);
layoutView(view, width, 4500);
WebView webView = view.findViewById(R.id.fiction_view);
WebSettings webSettings = webView.getSettings();
webSettings.setJavaScriptCanOpenWindowsAutomatically(true);
webSettings.setUseWideViewPort(true);//设置webview推荐使用的窗口
webSettings.setLoadWithOverviewMode(true);//设置webview加载的页面的模式
webSettings.setDisplayZoomControls(false);//隐藏webview缩放按钮
webSettings.setJavaScriptEnabled(true); // 设置支持javascript脚本
webSettings.setAllowFileAccess(true); // 允许访问文件
webSettings.setBuiltInZoomControls(true); // 设置显示缩放按钮
webSettings.setSupportZoom(true); // 支持缩放
webSettings.setBuiltInZoomControls(true);
webView.getSettings().setUseWideViewPort(true);
webView.getSettings().setLayoutAlgorithm(WebSettings.LayoutAlgorithm.NARROW_COLUMNS);
webView.getSettings().setLoadWithOverviewMode(true);
webView.getSettings().setBlockNetworkImage(false);//解决图片不显示
ImageView tvQR = view.findViewById(R.id.fiction_qr);
webView.loadUrl(webUrl);
tvQR.setImageBitmap(EncodingUtils.createQRCode(qrUrl, 1000, 1000, null));
final boolean[] isShow = {true};
webView.setWebChromeClient(new WebChromeClient() {
@Override
public void onProgressChanged(WebView webView, int newProgress) {
super.onProgressChanged(webView, newProgress);
if (newProgress == 100 && isShow[0]) {
isShow[0] = false;
new Thread(() -> {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
((Activity) context).runOnUiThread(new Runnable() {
@Override
public void run() {
getBitmap(view, rmb, 4500);
}
});
}).start();
}
}
});
}
最终图片被成功的分享出去了,在这里还需要注意的一点就是,因为webview全部加载完毕需要时间,所以我们必须等webview加载完成后才可以对View进行截图,否则的话,截图出去的内容页很可能是黑色的,那是因为内容没有被截取到。