当前位置: 代码迷 >> 综合 >> android后台动态创建图片并实现微信分享
  详细解决方案

android后台动态创建图片并实现微信分享

热度:97   发布时间:2023-10-19 07:06:08.0

今天就记录一下。

先说明一下,之前没有做过类似的东西,百度了一两天才知道,说来很惭愧、有点笨,只能这样说。

在我的脑里只明白,如果要动态创建图片:

一、就是new 嘛

二、就是LayoutInflater.from()这种。

而微信分享图片到朋友圈,这种不可能new textview或者Imageview,所以用第二种,LayoutInflater,加载布局的父类引用view,索性就开始干,结果,跳转到微信的界面图片直接就是空白图片,一直以为是没有把数据加入进去,反复地测试数据是有点,但还是空白图片,百度了一下,View.getDrawingCache() 只适用于分享的View已经完整展示在用户的屏幕上,超出屏幕范围内的内容是不在生成的Bitmap内的。

一、

大家可以看看这个解释:android后台通过View生成分享图片

虽然有点燥,但还是和我经过几个小时测试得出结论相差不多需要展示在界面才能根据view的宽高:

Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_4444);

这里用的ARGB_4444是16位的,可以用ARGB_8888 32位的,为了防止图片太大,分享不成功,把图片分辨率弄低一点,展示一下view下生成代码:

View view = inflater.inflate(R.layout.dialog, null, false);
private void checkAndRequestSavePermission(View view, int type) {//判断当前系统的SDK版本是否大于23if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {//如果当前申请的权限没有授权if (checkSelfPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {//请求权限requestPermissions(new String[]{WRITE_EXTERNAL_STORAGE}, 1);} else {//已经授权了就走这条分支savePic(view, type);}} else {savePic(view, type);}}

上面有个权限是,生成图片需要把图片保存在手机相册里面。

 private void savePic(final View view, final int type) {view.post(new Runnable() {@Overridepublic void run() {//获取view 长宽int width = view.getWidth();int height = view.getHeight();//若传入的view长或宽为小于等于0,则返回,不生成图片if (width <= 0 || height <= 0) {return;}//生成一个ARGB8888的bitmap,宽度和高度为传入view的宽高bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_4444);//根据bitmap生成一个画布Canvas canvas = new Canvas(bitmap);//注意:这里是解决图片透明度问题,给底色上白色,不然是透明色背景可能会很难看,若存储时保存的为png格式的图,则无需此步骤canvas.drawColor(Color.WHITE);view.draw(canvas);//不清晰,应该是压缩的厉害,很模糊
//                view.setDrawingCacheEnabled(true);
//                view.buildDrawingCache();
//                view.setBackgroundColor(Color.WHITE);
//                bitmap = BitmapUtils.reduce(view.getDrawingCache(),500, 500, true);//把bitmip保存到手机本地path = BitmapUtils.saveImage(bitmap, context);if (TextUtils.isEmpty(path)) {showMessage("保存图片失败");} else {//这里是需要实现的图片地址path是String}}});}
 public static String saveImage(Bitmap bmp, Context context) {File appDir = new File(Environment.getExternalStorageDirectory(), "自己定义");if (!appDir.exists()) {appDir.mkdir();}String fileName = System.currentTimeMillis() + ".jpg";File file = new File(appDir, fileName);try {FileOutputStream fos = new FileOutputStream(file);bmp.compress(Bitmap.CompressFormat.JPEG, 100, fos);fos.flush();fos.close();context.sendBroadcast(new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE).setData(Uri.fromFile(file)));//更新相册广播return file.getPath();} catch (FileNotFoundException e) {e.printStackTrace();} catch (IOException e) {e.printStackTrace();}return null;}

二、

上面这种方法对于已经显示在屏幕上,是完全没有问题的,但是对不需要在屏幕上显示的view而不行,还是这个大神给的启发:

Android 后台生成长图并分享(非长截图)

这个是先自定义LinearLayout,在里面实现画布局方法,相当于后台操作,直接开始。

public class SaveImgLinearLayout extends LinearLayout {private Listener listener;private Context context;// 长图的宽度,默认为屏幕宽度private int longPictureWidth;// 长图两边的间距private int picMargin;private View rootView;// 被认定为长图的长宽比private int widthTop = 0;private int heightTop = 0;private int widthContent = 0;private int heightContent = 0;private int widthBottom = 0;private int heightBottom = 0;private ImageView imgTop, imgCenter;private LinearLayout llBottom;private GoodsDetail bean;public interface Listener {/*** 生成长图成功的回调** @param path 长图路径*/void onSuccess(String path);/*** 生成长图失败的回调*/void onFail();}public void setListener(Listener listener) {this.listener = listener;}public SaveImgLinearLayout(Context context, GoodsDetail bean, View view) {super(context);this.bean = bean;this.rootView = view;init(context);}public SaveImgLinearLayout(Context context) {super(context);init(context);}public SaveImgLinearLayout(Context context, @Nullable AttributeSet attrs) {super(context, attrs);init(context);}public SaveImgLinearLayout(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {super(context, attrs, defStyleAttr);init(context);}private void init(Context context) {this.context = context;longPictureWidth = ScreenUtils.getScreenWidth(context);picMargin = 40;initView();}private void initView() {imgTop = (ImageView) rootView.findViewById(R.id.image_top);imgCenter = (ImageView) rootView.findViewById(R.id.imageview_center);llBottom = (LinearLayout) rootView.findViewById(R.id.ll_buttom);//测量头、中、底部layoutView(imgTop);layoutView(imgCenter);layoutView(llBottom);widthTop = imgTop.getMeasuredWidth();heightTop = imgTop.getMeasuredHeight();widthContent = imgCenter.getMeasuredWidth();// 由于高度是可变的,这里需要用post方法算出imgCenter.post(new Runnable() {@Overridepublic void run() {heightContent = imgCenter.getHeight();}});widthBottom = llBottom.getMeasuredWidth();heightBottom = llBottom.getMeasuredHeight();}/*** 手动测量view宽高*/private void layoutView(View v) {
//获取屏幕宽高int width = ScreenUtils.getScreenWidth(context);int height = ScreenUtils.getScreenHeight(context);v.layout(0, 0, width, height);int measuredWidth = View.MeasureSpec.makeMeasureSpec(width, View.MeasureSpec.EXACTLY);int measuredHeight = View.MeasureSpec.makeMeasureSpec(Integer.MAX_VALUE >> 2, MeasureSpec.AT_MOST);v.measure(measuredWidth, measuredHeight);v.layout(0, 0, v.getMeasuredWidth(), v.getMeasuredHeight());}public void startDraw() {// 需要先下载全部需要用到的图片(用户头像、图片等),下载完成后再进行长图的绘制操作downloadAllImage();}private void downloadAllImage() {// 之类根据自己的逻辑进行图片的下载,此Demo为了简单,制作一个延时模拟下载过程new Thread(new Runnable() {@Overridepublic void run() {// 模拟下载图片的耗时操作,推荐使用:implementation 'com.liulishuo.filedownloader:library:1.7.3'try {Thread.sleep(500);} catch (InterruptedException e) {e.printStackTrace();}// 图片下载完成后,进行view的绘制// 模拟保存图片url、路径的键值对// 开始绘制viewdraw();}}).start();}private void draw() {// 创建空白画布Bitmap.Config config = Bitmap.Config.ARGB_8888;Bitmap bitmapAll;// 计算出最终生成的长图的高度 = 上、中、图片总高度、下等个个部分加起来int allBitmapHeight = heightTop + heightContent + heightBottom;try {bitmapAll = Bitmap.createBitmap(longPictureWidth, allBitmapHeight, config);} catch (Exception e) {e.printStackTrace();config = Bitmap.Config.RGB_565;bitmapAll = Bitmap.createBitmap(longPictureWidth, allBitmapHeight, config);}Canvas canvas = new Canvas(bitmapAll);canvas.drawColor(Color.WHITE);Paint paint = new Paint();paint.setAntiAlias(true);paint.setDither(true);paint.setFilterBitmap(true);// 绘制top viewif (widthTop <= 0 && heightTop <= 0 && widthContent <= 0 && heightContent <= 0 && widthBottom <= 0 && heightBottom <= 0) {return;}
//决定你布局显示的位置,如果设置为0 ,就会如fragment一样,都在0.0位置显示重叠在一起canvas.drawBitmap(getLinearLayoutBitmap(imgTop, widthTop, heightTop), 0, 0, paint);canvas.drawBitmap(getLinearLayoutBitmap(imgCenter, widthContent, heightContent), 0, heightTop, paint);canvas.drawBitmap(getLinearLayoutBitmap(llBottom, widthBottom, heightBottom), 0, heightTop + heightContent, paint);canvas.save();// 绘制content view
//        canvas.translate(MyDensity.dp2px(context, 20), heightTop);
//        staticLayout.draw(canvas);// 生成最终的文件,并压缩大小,这里使用的是:implementation 
'com.github.nanchen2251:CompressHelper:1.0.5'
//这里可以压缩,,我没有压缩,如果有需要可以压缩try {
//把图片保存在手机底部。String path = BitmapUtils.saveImage(bitmapAll, context);if (listener != null) {listener.onSuccess(path);}} catch (Exception e) {e.printStackTrace();if (listener != null) {listener.onFail();}}}private Bitmap getLinearLayoutBitmap(View imgTop, int w, int h) {Bitmap originBitmap = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);Canvas canvas = new Canvas(originBitmap);imgTop.draw(canvas);return resizeImage(originBitmap, longPictureWidth, h);}public Bitmap resizeImage(Bitmap origin, int newWidth, int newHeight) {if (origin == null) {return null;}int height = origin.getHeight();int width = origin.getWidth();float scaleWidth = ((float) newWidth) / width;float scaleHeight = ((float) newHeight) / height;Matrix matrix = new Matrix();matrix.postScale(scaleWidth, scaleHeight);Bitmap newBM = Bitmap.createBitmap(origin, 0, 0, width, height, matrix, false);if (!origin.isRecycled()) {origin.recycle();}return newBM;}public void removeListener() {this.listener = null;}}

使用时候,直接new  就行了,,然后调用startDraw()方法,就可以了。

至此,已经完了,希望大家给出意见,有什么更好的方法,提出来。

  相关解决方案