hello大家好,我是斯普润,很久没有更新博客了。因为最近一直在赶项目,不停加班。难得有时间闲下来写写博客。最近也在抽时间学习flutter,作为一枚程序猿当然不能停止学习的脚步啦~

说远了,今天分享下用代码生成长图并保存到本地的功能。当点击分享按钮后,会在后台生成长图的Bitmap,点击保存会将Bitmap存到本地jpg文件。先来看看我实现的效果。

   

其实原理很简单,首先生成一个空白的画布,然后通过本地的xml布局文件获取layout,将layout转成Bitmap,通过Canvas绘制出来,唯一需要注意的就是计算高度。我这里将其拆分成了三块,头布局只有文字和头像,中布局全部是图片,尾布局高度指定,由于图片需要根据宽度去收缩放大,所以计算中布局稍微麻烦一点,将需要绘制的图片下载到本地,所以使用前需要先申请存储权限!将图片收缩或放大至指定宽度,计算出此时的图片高度,将所有图片高度与间距高度累加,就得到了中布局的总高度。

说了这么多,先来看我的代码吧~ 注释都有,就不过多解释了,有些工具类,你们替换一下就可以了,比如SharePreUtil、DimensionUtil、QRCodeUtil等等,不需要可以去掉

import android.Manifest;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.text.SpannableString;
import android.text.TextUtils;
import android.text.style.ForegroundColorSpan;
import android.util.AttributeSet;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.FrameLayout;
import android.widget.LinearLayout;
import android.widget.TextView;import androidx.annotation.Nullable;import com.liulishuo.filedownloader.BaseDownloadTask;
import com.liulishuo.filedownloader.FileDownloadListener;
import com.liulishuo.filedownloader.FileDownloader;
import com.tbruyelle.rxpermissions2.RxPermissions;import java.io.File;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;public class LongPoster extends LinearLayout {private String TAG = this.getClass().getName();private Context context;private View rootView;private Listener listener;private LinearLayout topViewLl, contentLl;private FrameLayout bottomViewFl;private TextView appNameTv, nameTv, courseNameTv, courseDetailTv, codeContentTv;// 长图的宽度,默认为屏幕宽度private int longPictureWidth;// 长图两边的间距private int leftRightMargin;// 图片的url集合private List<String> imageUrlList;// 保存下载后的图片url和路径键值对的链表private LinkedHashMap<String, String> localImagePathMap;//每张图的高度private Map<Integer, Integer> imgHeightMap;private int topHeight = 0;private int contentHeight = 0;private int bottomHeight = 0;//是否包含头像private boolean isContainAvatar = false;private Bitmap qrcodeBit;private List<Bitmap> tempList;public static void createPoster(InitialActivity activity, LongPosterBean bean, Listener listener) {new RxPermissions(activity).request(Manifest.permission.READ_EXTERNAL_STORAGE, Manifest.permission.WRITE_EXTERNAL_STORAGE).subscribe(granted -> {if (granted) {activity.showInfoProgressDialog(activity, "海报生成中...");LongPoster poster = new LongPoster(activity);poster.setListener(listener);poster.setCurData(bean);} else {ToastUtil.showShort(activity, "请获取存储权限");listener.onFail();}});}public LongPoster(Context context) {super(context);init(context);}public LongPoster(Context context, @Nullable AttributeSet attrs) {super(context, attrs);init(context);}public LongPoster(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {super(context, attrs, defStyleAttr);init(context);}public void removeListener() {this.listener = null;}public void setListener(Listener listener) {this.listener = listener;}private void init(Context context) {this.context = context;tempList = new ArrayList<>();//这里去获取屏幕高度,我这里默认1080longPictureWidth = 1080;leftRightMargin = DimensionUtil.dp2pxInt(15);rootView = LayoutInflater.from(context).inflate(R.layout.layout_draw_canvas, this, false);initView();}private void initView() {topViewLl = rootView.findViewById(R.id.ll_top_view);contentLl = rootView.findViewById(R.id.ll_content);bottomViewFl = rootView.findViewById(R.id.fl_bottom_view);appNameTv = rootView.findViewById(R.id.app_name_tv);nameTv = rootView.findViewById(R.id.tv_name);courseNameTv = rootView.findViewById(R.id.tv_course_name);courseDetailTv = rootView.findViewById(R.id.tv_course_detail_name);codeContentTv = rootView.findViewById(R.id.qr_code_content_tv);imageUrlList = new ArrayList<>();localImagePathMap = new LinkedHashMap<>();imgHeightMap = new HashMap<>();}public void setCurData(LongPosterBean bean) {imageUrlList.clear();localImagePathMap.clear();String icon = SharedPreUtil.getString("userIcon", "");if (!TextUtils.isEmpty(icon)) {imageUrlList.add(StringUtil.handleImageUrl(icon));isContainAvatar = true;}if (bean.getPhotoList() != null) {for (String str : bean.getPhotoList()) {imageUrlList.add(StringUtil.handleImageUrl(str));}}appNameTv.setText(R.string.app_name);nameTv.setText(SharedPreUtil.getString("userNickName", ""));String courseNameStr = "我在" + getResources().getString(R.string.app_name) + "学" + bean.getCourseName();SpannableString ss = new SpannableString(courseNameStr);ss.setSpan(new ForegroundColorSpan(Color.parseColor("#333333")),courseNameStr.length() - bean.getCourseName().length(), courseNameStr.length(),SpannableString.SPAN_EXCLUSIVE_EXCLUSIVE);courseNameTv.setText(ss);courseDetailTv.setText(bean.getDetailName());codeContentTv.setText("扫描二维码\n查看" + bean.getCourseName());if (!TextUtils.isEmpty(bean.getQrCodeUrl())) {int width = (int) DimensionUtil.dp2px(120);qrcodeBit = QRCodeUtil.createQRCodeBitmap(bean.getQrCodeUrl(), width, width);tempList.add(qrcodeBit);}downloadAllPic();}private void downloadAllPic() {//下载方法,这里替换你选用的三方库,或者你可以选用我使用的这个三方库//implementation 'com.liulishuo.filedownloader:library:1.7.4'if (imageUrlList.isEmpty()) return;FileDownloader.setup(context);FileDownloadListener queueTarget = new FileDownloadListener() {@Overrideprotected void pending(BaseDownloadTask task, int soFarBytes, int totalBytes) {}@Overrideprotected void connected(BaseDownloadTask task, String etag, boolean isContinue, int soFarBytes, int totalBytes) {}@Overrideprotected void progress(BaseDownloadTask task, int soFarBytes, int totalBytes) {}@Overrideprotected void blockComplete(BaseDownloadTask task) {}@Overrideprotected void retry(final BaseDownloadTask task, final Throwable ex, final int retryingTimes, final int soFarBytes) {}@Overrideprotected void completed(BaseDownloadTask task) {localImagePathMap.put(task.getUrl(), task.getTargetFilePath());if (localImagePathMap.size() == imageUrlList.size()) {//全部图片下载完成开始绘制measureHeight();drawPoster();}}@Overrideprotected void paused(BaseDownloadTask task, int soFarBytes, int totalBytes) {}@Overrideprotected void error(BaseDownloadTask task, Throwable e) {listener.onFail();e.printStackTrace();}@Overrideprotected void warn(BaseDownloadTask task) {}};for (String url : imageUrlList) {String storePath = BitmapUtil.getImgFilePath();FileDownloader.getImpl().create(url).setCallbackProgressTimes(0).setListener(queueTarget).setPath(storePath).asInQueueTask().enqueue();}FileDownloader.getImpl().start(queueTarget, true);}private void measureHeight() {layoutView(topViewLl);layoutView(contentLl);layoutView(bottomViewFl);topHeight = topViewLl.getMeasuredHeight();//原始高度加上图片总高度contentHeight = contentLl.getMeasuredHeight() + getAllImageHeight();bottomHeight = bottomViewFl.getMeasuredHeight();
//        LogUtil.d(TAG, "drawLongPicture layout top view = " + topHeight + " × " + longPictureWidth);
//        LogUtil.d(TAG, "drawLongPicture layout llContent view = " + contentHeight);
//        LogUtil.d(TAG, "drawLongPicture layout bottom view = " + bottomHeight);}/*** 绘制方法*/private void drawPoster() {// 计算出最终生成的长图的高度 = 上、中、图片总高度、下等个个部分加起来int allBitmapHeight = topHeight + contentHeight + bottomHeight;// 创建空白画布Bitmap.Config config = Bitmap.Config.RGB_565;Bitmap 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 viewBitmap topBit = BitmapUtil.getLayoutBitmap(topViewLl, longPictureWidth, topHeight);canvas.drawBitmap(topBit, 0, 0, paint);//绘制头像Bitmap avatarBit;if (isContainAvatar) {int aWidth = (int) DimensionUtil.dp2px(77);avatarBit = BitmapUtil.resizeImage(BitmapFactory.decodeFile(localImagePathMap.get(imageUrlList.get(0))), aWidth, aWidth);} else {avatarBit = BitmapUtil.drawableToBitmap(context.getDrawable(R.drawable.placeholder));}if (avatarBit != null) {avatarBit = BitmapUtil.getOvalBitmap(avatarBit, (int) DimensionUtil.dp2px(38));canvas.drawBitmap(avatarBit, DimensionUtil.dp2px(20), DimensionUtil.dp2px(70), paint);}//绘制中间图片列表if (isContainAvatar && imageUrlList.size() > 1) {Bitmap bitmapTemp;int top = (int) (topHeight + DimensionUtil.dp2px(20));for (int i = 1; i < imageUrlList.size(); i++) {String filePath = localImagePathMap.get(imageUrlList.get(i));bitmapTemp = BitmapUtil.fitBitmap(BitmapFactory.decodeFile(filePath),longPictureWidth - leftRightMargin * 2);if (i > 1)top += imgHeightMap.get(i - 1) + DimensionUtil.dp2px(10);canvas.drawBitmap(bitmapTemp, leftRightMargin, top, paint);tempList.add(bitmapTemp);}} else if (!isContainAvatar && !imageUrlList.isEmpty()) {Bitmap bitmapTemp;int top = (int) (topHeight + DimensionUtil.dp2px(20));for (int i = 0; i < imageUrlList.size(); i++) {String filePath = localImagePathMap.get(imageUrlList.get(i));bitmapTemp = BitmapUtil.fitBitmap(BitmapFactory.decodeFile(filePath),longPictureWidth - leftRightMargin * 2);if (i > 0)top += imgHeightMap.get(i - 1) + DimensionUtil.dp2px(10);canvas.drawBitmap(bitmapTemp, leftRightMargin, top, paint);tempList.add(bitmapTemp);}}// 绘制bottom viewBitmap bottomBit = BitmapUtil.getLayoutBitmap(bottomViewFl, longPictureWidth, bottomHeight);canvas.drawBitmap(bottomBit, 0, topHeight + contentHeight, paint);// 绘制QrCode//if (qrcodeBit != null)//canvas.drawBitmap(qrcodeBit, longPictureWidth - DimensionUtil.dp2px(150),//topHeight + contentHeight + DimensionUtil.dp2px(15), paint);//保存最终的图片String time = String.valueOf(System.currentTimeMillis());boolean state = BitmapUtil.saveImage(bitmapAll, context.getExternalCacheDir() +File.separator, time, Bitmap.CompressFormat.JPEG, 80);//绘制回调if (listener != null) {if (state) {listener.onSuccess(context.getExternalCacheDir() + File.separator + time);} else {listener.onFail();}}//清空所有BitmaptempList.add(topBit);tempList.add(avatarBit);tempList.add(bottomBit);tempList.add(bitmapAll);for (Bitmap bit : tempList) {if (bit != null && !bit.isRecycled()) {bit.recycle();}}tempList.clear();//绘制完成,删除所有保存的图片for (int i = 0; i < imageUrlList.size(); i++) {String path = localImagePathMap.get(imageUrlList.get(i));File file = new File(path);if (file.exists()) {file.delete();}}}/*** 获取当前下载所有图片的高度,忽略头像*/private int getAllImageHeight() {imgHeightMap.clear();int height = 0;int startIndex = 0;int cutNum = 1;if (isContainAvatar) {cutNum = 2;startIndex = 1;}for (int i = startIndex; i < imageUrlList.size(); i++) {Bitmap tamp = BitmapUtil.fitBitmap(BitmapFactory.decodeFile(localImagePathMap.get(imageUrlList.get(i))),longPictureWidth - leftRightMargin * 2);height += tamp.getHeight();imgHeightMap.put(i, tamp.getHeight());tempList.add(tamp);}height = (int) (height + DimensionUtil.dp2px(10) * (imageUrlList.size() - cutNum));return height;}/*** 手动测量view宽高*/private void layoutView(View v) {v.layout(0, 0, DoukouApplication.screenWidth, DoukouApplication.screenHeight);int measuredWidth = View.MeasureSpec.makeMeasureSpec(DoukouApplication.screenWidth, 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 interface Listener {/*** 生成长图成功的回调** @param path 长图路径*/void onSuccess(String path);/*** 生成长图失败的回调*/void onFail();}
}

接下来是界面布局,由于图片先下载再绘制的,所以不需要图片控件,只需要预留出图片的位置就可以了~

<?xml version="1.0" encoding="utf-8"?>
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"android:layout_width="match_parent"android:layout_height="match_parent"><LinearLayoutandroid:layout_width="match_parent"android:layout_height="wrap_content"android:background="@color/white"android:orientation="vertical"><LinearLayoutandroid:id="@+id/ll_top_view"android:layout_width="match_parent"android:layout_height="wrap_content"android:orientation="vertical"android:paddingLeft="15dp"android:paddingRight="15dp"><LinearLayoutandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_gravity="center_horizontal"android:layout_marginTop="25dp"android:gravity="center_vertical"android:orientation="horizontal"><TextViewandroid:id="@+id/app_name_tv"android:layout_width="wrap_content"android:layout_height="wrap_content"android:textColor="#fffb4e90"android:textSize="18sp" /><Viewandroid:layout_width="1dp"android:layout_height="14dp"android:layout_marginHorizontal="10dp"android:background="@color/colorPrimary" /><TextViewandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:textColor="#fffb4e90"android:textSize="18sp" /></LinearLayout><FrameLayoutandroid:layout_width="match_parent"android:layout_height="wrap_content"android:layout_marginTop="20dp"><TextViewandroid:id="@+id/tv_name"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_marginStart="87dp"android:layout_marginTop="8dp"android:textColor="@color/c33"android:textSize="18sp" /><TextViewandroid:id="@+id/tv_course_name"android:layout_width="match_parent"android:layout_height="wrap_content"android:layout_marginStart="87dp"android:layout_marginTop="43dp"android:textColor="@color/c66"android:textSize="18sp" /></FrameLayout><TextViewandroid:id="@+id/tv_course_detail_name"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_gravity="center_horizontal"android:layout_marginTop="28dp"android:background="@drawable/shape_black_radius2"android:paddingHorizontal="22dp"android:paddingVertical="10dp"android:textColor="#ffffffff"android:textSize="15sp" /></LinearLayout><LinearLayoutandroid:id="@+id/ll_content"android:layout_width="match_parent"android:layout_height="wrap_content"android:orientation="vertical"android:paddingLeft="15dp"android:paddingTop="20dp"android:paddingRight="15dp"android:paddingBottom="10dp" /><FrameLayoutandroid:id="@+id/fl_bottom_view"android:layout_width="match_parent"android:layout_height="wrap_content"android:gravity="center_vertical"android:orientation="horizontal"android:paddingLeft="15dp"android:paddingRight="15dp"android:paddingBottom="20dp"><ImageViewandroid:layout_width="match_parent"android:layout_height="150dp"android:scaleType="fitXY"android:src="@drawable/bg_qr_code" /><TextViewandroid:id="@+id/qr_code_content_tv"android:layout_width="175dp"android:layout_height="wrap_content"android:layout_gravity="center_vertical"android:layout_marginLeft="15dp"android:ellipsize="end"android:maxLines="3"android:textColor="@color/white"android:textSize="15sp" /></FrameLayout></LinearLayout></ScrollView>

BitmapUtil工具类~

import android.Manifest;
import android.content.Context;
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.PixelFormat;
import android.graphics.PorterDuff;
import android.graphics.PorterDuffXfermode;
import android.graphics.Rect;
import android.graphics.RectF;
import android.graphics.drawable.Drawable;
import android.media.ExifInterface;
import android.net.Uri;
import android.os.Build;
import android.os.Environment;
import android.renderscript.Allocation;
import android.renderscript.Element;
import android.renderscript.RenderScript;
import android.renderscript.ScriptIntrinsicBlur;
import android.text.TextUtils;
import android.util.Log;
import android.view.View;
import android.view.ViewGroup;import androidx.annotation.RequiresApi;
import androidx.fragment.app.FragmentActivity;import com.tbruyelle.rxpermissions2.RxPermissions;import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.UUID;public class BitmapUtil {private static final String TAG = "BitmapUtil";/*** 将Bitmap转成图片保存本地*/public static boolean saveImage(Bitmap bitmap, String filePath, String filename, Bitmap.CompressFormat format, int quality) {if (quality > 100) {Log.d("saveImage", "quality cannot be greater that 100");return false;}File file;FileOutputStream out = null;try {switch (format) {case PNG:file = new File(filePath, filename);out = new FileOutputStream(file);return bitmap.compress(Bitmap.CompressFormat.PNG, quality, out);case JPEG:file = new File(filePath, filename);out = new FileOutputStream(file);return bitmap.compress(Bitmap.CompressFormat.JPEG, quality, out);default:file = new File(filePath, filename + ".png");out = new FileOutputStream(file);return bitmap.compress(Bitmap.CompressFormat.PNG, quality, out);}} catch (Exception e) {e.printStackTrace();} finally {try {if (out != null) {out.close();}} catch (IOException e) {e.printStackTrace();}}return false;}/*** drawable 转 bitmap*/public static Bitmap drawableToBitmap(Drawable drawable) {// 取 drawable 的长宽int w = drawable.getIntrinsicWidth();int h = drawable.getIntrinsicHeight();// 取 drawable 的颜色格式Bitmap.Config config = drawable.getOpacity() != PixelFormat.OPAQUE ? Bitmap.Config.ARGB_8888 : Bitmap.Config.RGB_565;// 建立对应 bitmapBitmap bitmap = Bitmap.createBitmap(w, h, config);// 建立对应 bitmap 的画布Canvas canvas = new Canvas(bitmap);drawable.setBounds(0, 0, w, h);// 把 drawable 内容画到画布中drawable.draw(canvas);return bitmap;}public static void saveImage(FragmentActivity context, Bitmap bmp, boolean recycle) {new RxPermissions(context).request(Manifest.permission.READ_EXTERNAL_STORAGE, Manifest.permission.WRITE_EXTERNAL_STORAGE).subscribe(granted -> {if (granted) {if (BitmapUtil.saveImageToGallery(context, bmp)) {ToastUtil.showShort(context, "保存成功");} else {ToastUtil.showShort(context, "保存失败");}} else {ToastUtil.showShort(context, "请获取存储权限");}if (recycle) bmp.recycle();});}//保存图片到指定路径private static boolean saveImageToGallery(FragmentActivity context, Bitmap bmp) {// 首先保存图片String storePath = Environment.getExternalStorageDirectory().getAbsolutePath() + File.separator +Environment.DIRECTORY_PICTURES + File.separator + "test";File appDir = new File(storePath);if (!appDir.exists()) {appDir.mkdir();}String fileName = System.currentTimeMillis() + ".jpg";File file = new File(appDir, fileName);try {FileOutputStream fos = new FileOutputStream(file);//通过io流的方式来压缩保存图片boolean isSuccess = bmp.compress(Bitmap.CompressFormat.JPEG, 60, fos);fos.flush();fos.close();//把文件插入到系统图库
//            MediaStore.Images.Media.insertImage(context.getContentResolver(), bmp, fileName, null);//保存图片后发送广播通知更新数据库Intent intent = new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE);Uri uri = Uri.fromFile(new File(file.getAbsolutePath()));LogUtil.e("路径============", file.getAbsolutePath());intent.setData(uri);context.sendBroadcast(intent);return isSuccess;} catch (IOException e) {e.printStackTrace();}return false;}public static String getImgFilePath() {String storePath = Environment.getExternalStorageDirectory().getAbsolutePath() + File.separator +Environment.DIRECTORY_PICTURES + File.separator + "test" + File.separator;File appDir = new File(storePath);if (!appDir.exists()) {appDir.mkdir();}return storePath + UUID.randomUUID().toString().replace("-", "") + ".jpg";}/**** 得到指定半径的圆形Bitmap* @param bitmap 图片* @param radius 半径* @return bitmap*/public static Bitmap getOvalBitmap(Bitmap bitmap, int radius) {Bitmap output = Bitmap.createBitmap(bitmap.getWidth(), bitmap.getHeight(), Bitmap.Config.ARGB_8888);Canvas canvas = new Canvas(output);int width = bitmap.getWidth();int height = bitmap.getHeight();float scaleWidth = ((float) 2 * radius) / width;Matrix matrix = new Matrix();matrix.postScale(scaleWidth, scaleWidth);bitmap = Bitmap.createBitmap(bitmap, 0, 0, width, height, matrix, true);final int color = 0xff424242;final Paint paint = new Paint();final Rect rect = new Rect(0, 0, bitmap.getWidth(), bitmap.getHeight());final RectF rectF = new RectF(rect);paint.setAntiAlias(true);canvas.drawARGB(0, 0, 0, 0);paint.setColor(color);canvas.drawOval(rectF, paint);paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN));canvas.drawBitmap(bitmap, rect, rect, paint);return output;}/*** layout布局转Bitmap** @param layout 布局* @param w      宽* @param h      高* @return bitmap*/public static Bitmap getLayoutBitmap(ViewGroup layout, int w, int h) {Bitmap originBitmap = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);Canvas canvas = new Canvas(originBitmap);layout.draw(canvas);return resizeImage(originBitmap, w, h);}public static 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;}/*** fuction: 设置固定的宽度,高度随之变化,使图片不会变形** @param target   需要转化bitmap参数* @param newWidth 设置新的宽度* @return*/public static Bitmap fitBitmap(Bitmap target, int newWidth) {int width = target.getWidth();int height = target.getHeight();Matrix matrix = new Matrix();float scaleWidth = ((float) newWidth) / width;// float scaleHeight = ((float)newHeight) / height;int newHeight = (int) (scaleWidth * height);matrix.postScale(scaleWidth, scaleWidth);// Bitmap result = Bitmap.createBitmap(target,0,0,width,height,// matrix,true);Bitmap bmp = Bitmap.createBitmap(target, 0, 0, width, height, matrix,true);if (target != null && !target.equals(bmp) && !target.isRecycled()) {target.recycle();target = null;}return bmp;// Bitmap.createBitmap(target, 0, 0, width, height, matrix,// true);}
}

嗯,好了,大致代码就是以上这些,不过有些方法需要替换成你们自己的哦~

Android通过代码生成长图并保存本地相关推荐

  1. android 漫画加载方案,Android加载长图的多种方案分享

    背景介绍 在某些特定场景下,我们需要考虑加载长图的需求,比如加载一幅<清明上河图>,这个好像有点过分了,那就加载1/2的<清明上河图>吧... 那TMD还不是一样道理. 言归正 ...

  2. Android加载长图滑动显示

    1.记录下学到的Android加载长图写法以备后用 首先准备一张长图.这里把图片先放到项目的 assets文件夹下:命名为big.png 然后开始自定义显示长图的view :BigView impor ...

  3. python3:android手机截长图的小工具

    这个工具写下来遇到了不少坑,直到现在还没有完全解决,先记录下来吧,后面有机会再修改,或是有心的同学帮忙分析一下为什么? 主要实现以下功能: 1. 在手机上截一张图至桌面. 2. 在手机在连接截多张图片 ...

  4. android 照片拼接长图_最智能的 Android 长图拼接应用:图片自动连接

    点击「添加」图标,按拼接顺序勾选图片(免费版上限为 5 张),倘若不小心弄错了顺序,无需清除重新添加,可以通过按住图片拖动来进行排列.一切准备妥当之后,下一步就可以点击「连接!」来生成长图了. 生成的 ...

  5. android 照片拼接长图_Android拼接合并图片生成长图-阿里云开发者社区

    Android拼接合并图片生成长图 代码实现合并两张图片,以第一张图片的宽度为标准,如果被合并的第二张图片宽度和第一张不同,那么就以第一张图片的宽度为准线,对第二张图片进行缩放. 假设根目录的Pict ...

  6. android WebView截长图实现

    1.先简单介绍下webview截屏,看代码: //开启缓存 webview.setDrawingCacheEnabled(true); webview.buildDrawingCache();Bitm ...

  7. android 照片拼接长图_我才发现,微信里面有一个功能,能将手机照片自动拼成长图...

    微信朋友圈发图片有限制,一次只能发9张,超过就发送不了.那么喜欢拍照的朋友肯定肯定想一次性多分享几张,其实微信自带拼接长图功能,多张照片上传,就能变成一张长图,一次性在朋友圈分享几十张图片都可以. 微 ...

  8. Android 生成分享长图并且添加全图水印

    转载自 : http://blog.csdn.net/gengqiquan/article/details/65938021 领导最近觉得携程的截屏生成长图分享效果比较好,所以我们也加了个:产品觉得分 ...

  9. android 照片拼接长图_手机照片拼接长图软件|照片拼接长图app下载v2.0-乐游网软件下载...

    <照片拼接长图app>是一款功能非常强大的微信照片拼接长图工具.名叫<照片拼贴>,能够直接为用户提供微信图片,QQ图片以及手机中的各种照片拼接和编辑的功能,让你随时随地拼图片, ...

最新文章

  1. windows下捕获dump
  2. 99% 的人都能看懂的「补偿」以及最佳实践
  3. html 边框循环变色,方框用过渡走一圈变色用css怎么实现
  4. 谨以此片,献给你身边的产品经理
  5. html访问java接口出现缓存_一个牛逼的多级缓存实现方案
  6. Dynamips 简介
  7. 实际编程题----CT扫描
  8. MySql索引原理与使用大全
  9. 【渝粤教育】 国家开放大学2020年春季 1373特殊教育概论 参考试题
  10. 10kv电压互感器型号_电流互感器结构及原理
  11. lintcode 7. 二叉树的序列化和反序列化 Python代码
  12. 公司的摄像头密码要统一
  13. iOS代码质量要求_iOS 无需越狱修改和平精英极限画质
  14. 杰理AD142A AD145A系列芯片的功能简介
  15. 在东京大学感受_东京最好的街头小吃在哪里找到
  16. 用VB制作自己的IE网页浏览器
  17. 磁珠 符号_圆形磁珠规格常用指南「多图」
  18. 中国人工智能领域企业分类(附未来企业排行)
  19. C#学习之 调用 AForge.NET Framework 启动摄像头
  20. Vert.x(vertx) 连接MySQL、Oracle数据库

热门文章

  1. 效率软件|在Windows下最快的磁盘空间占用情况分析软件——WizTree
  2. SSD训练的优化器们
  3. Android 中Canvas的save(),saveLayer()和restore()解析
  4. 驱动人生禁止win7、win10系统弹窗和无法识别USB设备问题解决方案
  5. TabLayout动态添加Tab (动态设置TabMod)
  6. 美团后端笔试2022.08.13
  7. 数字图像处理(基本知识点二)
  8. 南京铁道职业技术学校计算机应用技术,南京铁道职业技术学院
  9. The Scroll Marked Nine 羊皮卷之九
  10. python画彩虹圈_彩虹圈,可能还是宇舶玩的溜