当前位置:   article > 正文

Android通过代码生成长图并保存本地_android 生成图片保存到本地 安卓自动生成图片

android 生成图片保存到本地 安卓自动生成图片

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

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

   

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

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

  1. import android.Manifest;
  2. import android.content.Context;
  3. import android.graphics.Bitmap;
  4. import android.graphics.BitmapFactory;
  5. import android.graphics.Canvas;
  6. import android.graphics.Color;
  7. import android.graphics.Paint;
  8. import android.text.SpannableString;
  9. import android.text.TextUtils;
  10. import android.text.style.ForegroundColorSpan;
  11. import android.util.AttributeSet;
  12. import android.view.LayoutInflater;
  13. import android.view.View;
  14. import android.widget.FrameLayout;
  15. import android.widget.LinearLayout;
  16. import android.widget.TextView;
  17. import androidx.annotation.Nullable;
  18. import com.liulishuo.filedownloader.BaseDownloadTask;
  19. import com.liulishuo.filedownloader.FileDownloadListener;
  20. import com.liulishuo.filedownloader.FileDownloader;
  21. import com.tbruyelle.rxpermissions2.RxPermissions;
  22. import java.io.File;
  23. import java.util.ArrayList;
  24. import java.util.HashMap;
  25. import java.util.LinkedHashMap;
  26. import java.util.List;
  27. import java.util.Map;
  28. public class LongPoster extends LinearLayout {
  29. private String TAG = this.getClass().getName();
  30. private Context context;
  31. private View rootView;
  32. private Listener listener;
  33. private LinearLayout topViewLl, contentLl;
  34. private FrameLayout bottomViewFl;
  35. private TextView appNameTv, nameTv, courseNameTv, courseDetailTv, codeContentTv;
  36. // 长图的宽度,默认为屏幕宽度
  37. private int longPictureWidth;
  38. // 长图两边的间距
  39. private int leftRightMargin;
  40. // 图片的url集合
  41. private List<String> imageUrlList;
  42. // 保存下载后的图片url和路径键值对的链表
  43. private LinkedHashMap<String, String> localImagePathMap;
  44. //每张图的高度
  45. private Map<Integer, Integer> imgHeightMap;
  46. private int topHeight = 0;
  47. private int contentHeight = 0;
  48. private int bottomHeight = 0;
  49. //是否包含头像
  50. private boolean isContainAvatar = false;
  51. private Bitmap qrcodeBit;
  52. private List<Bitmap> tempList;
  53. public static void createPoster(InitialActivity activity, LongPosterBean bean, Listener listener) {
  54. new RxPermissions(activity).request(Manifest.permission.READ_EXTERNAL_STORAGE, Manifest.permission.WRITE_EXTERNAL_STORAGE)
  55. .subscribe(granted -> {
  56. if (granted) {
  57. activity.showInfoProgressDialog(activity, "海报生成中...");
  58. LongPoster poster = new LongPoster(activity);
  59. poster.setListener(listener);
  60. poster.setCurData(bean);
  61. } else {
  62. ToastUtil.showShort(activity, "请获取存储权限");
  63. listener.onFail();
  64. }
  65. });
  66. }
  67. public LongPoster(Context context) {
  68. super(context);
  69. init(context);
  70. }
  71. public LongPoster(Context context, @Nullable AttributeSet attrs) {
  72. super(context, attrs);
  73. init(context);
  74. }
  75. public LongPoster(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
  76. super(context, attrs, defStyleAttr);
  77. init(context);
  78. }
  79. public void removeListener() {
  80. this.listener = null;
  81. }
  82. public void setListener(Listener listener) {
  83. this.listener = listener;
  84. }
  85. private void init(Context context) {
  86. this.context = context;
  87. tempList = new ArrayList<>();
  88. //这里去获取屏幕高度,我这里默认1080
  89. longPictureWidth = 1080;
  90. leftRightMargin = DimensionUtil.dp2pxInt(15);
  91. rootView = LayoutInflater.from(context).inflate(R.layout.layout_draw_canvas, this, false);
  92. initView();
  93. }
  94. private void initView() {
  95. topViewLl = rootView.findViewById(R.id.ll_top_view);
  96. contentLl = rootView.findViewById(R.id.ll_content);
  97. bottomViewFl = rootView.findViewById(R.id.fl_bottom_view);
  98. appNameTv = rootView.findViewById(R.id.app_name_tv);
  99. nameTv = rootView.findViewById(R.id.tv_name);
  100. courseNameTv = rootView.findViewById(R.id.tv_course_name);
  101. courseDetailTv = rootView.findViewById(R.id.tv_course_detail_name);
  102. codeContentTv = rootView.findViewById(R.id.qr_code_content_tv);
  103. imageUrlList = new ArrayList<>();
  104. localImagePathMap = new LinkedHashMap<>();
  105. imgHeightMap = new HashMap<>();
  106. }
  107. public void setCurData(LongPosterBean bean) {
  108. imageUrlList.clear();
  109. localImagePathMap.clear();
  110. String icon = SharedPreUtil.getString("userIcon", "");
  111. if (!TextUtils.isEmpty(icon)) {
  112. imageUrlList.add(StringUtil.handleImageUrl(icon));
  113. isContainAvatar = true;
  114. }
  115. if (bean.getPhotoList() != null) {
  116. for (String str : bean.getPhotoList()) {
  117. imageUrlList.add(StringUtil.handleImageUrl(str));
  118. }
  119. }
  120. appNameTv.setText(R.string.app_name);
  121. nameTv.setText(SharedPreUtil.getString("userNickName", ""));
  122. String courseNameStr = "我在" + getResources().getString(R.string.app_name) + "学" + bean.getCourseName();
  123. SpannableString ss = new SpannableString(courseNameStr);
  124. ss.setSpan(new ForegroundColorSpan(Color.parseColor("#333333")),
  125. courseNameStr.length() - bean.getCourseName().length(), courseNameStr.length(),
  126. SpannableString.SPAN_EXCLUSIVE_EXCLUSIVE);
  127. courseNameTv.setText(ss);
  128. courseDetailTv.setText(bean.getDetailName());
  129. codeContentTv.setText("扫描二维码\n查看" + bean.getCourseName());
  130. if (!TextUtils.isEmpty(bean.getQrCodeUrl())) {
  131. int width = (int) DimensionUtil.dp2px(120);
  132. qrcodeBit = QRCodeUtil.createQRCodeBitmap(bean.getQrCodeUrl(), width, width);
  133. tempList.add(qrcodeBit);
  134. }
  135. downloadAllPic();
  136. }
  137. private void downloadAllPic() {
  138. //下载方法,这里替换你选用的三方库,或者你可以选用我使用的这个三方库
  139. //implementation 'com.liulishuo.filedownloader:library:1.7.4'
  140. if (imageUrlList.isEmpty()) return;
  141. FileDownloader.setup(context);
  142. FileDownloadListener queueTarget = new FileDownloadListener() {
  143. @Override
  144. protected void pending(BaseDownloadTask task, int soFarBytes, int totalBytes) {
  145. }
  146. @Override
  147. protected void connected(BaseDownloadTask task, String etag, boolean isContinue, int soFarBytes, int totalBytes) {
  148. }
  149. @Override
  150. protected void progress(BaseDownloadTask task, int soFarBytes, int totalBytes) {
  151. }
  152. @Override
  153. protected void blockComplete(BaseDownloadTask task) {
  154. }
  155. @Override
  156. protected void retry(final BaseDownloadTask task, final Throwable ex, final int retryingTimes, final int soFarBytes) {
  157. }
  158. @Override
  159. protected void completed(BaseDownloadTask task) {
  160. localImagePathMap.put(task.getUrl(), task.getTargetFilePath());
  161. if (localImagePathMap.size() == imageUrlList.size()) {
  162. //全部图片下载完成开始绘制
  163. measureHeight();
  164. drawPoster();
  165. }
  166. }
  167. @Override
  168. protected void paused(BaseDownloadTask task, int soFarBytes, int totalBytes) {
  169. }
  170. @Override
  171. protected void error(BaseDownloadTask task, Throwable e) {
  172. listener.onFail();
  173. e.printStackTrace();
  174. }
  175. @Override
  176. protected void warn(BaseDownloadTask task) {
  177. }
  178. };
  179. for (String url : imageUrlList) {
  180. String storePath = BitmapUtil.getImgFilePath();
  181. FileDownloader.getImpl().create(url)
  182. .setCallbackProgressTimes(0)
  183. .setListener(queueTarget)
  184. .setPath(storePath)
  185. .asInQueueTask()
  186. .enqueue();
  187. }
  188. FileDownloader.getImpl().start(queueTarget, true);
  189. }
  190. private void measureHeight() {
  191. layoutView(topViewLl);
  192. layoutView(contentLl);
  193. layoutView(bottomViewFl);
  194. topHeight = topViewLl.getMeasuredHeight();
  195. //原始高度加上图片总高度
  196. contentHeight = contentLl.getMeasuredHeight() + getAllImageHeight();
  197. bottomHeight = bottomViewFl.getMeasuredHeight();
  198. // LogUtil.d(TAG, "drawLongPicture layout top view = " + topHeight + " × " + longPictureWidth);
  199. // LogUtil.d(TAG, "drawLongPicture layout llContent view = " + contentHeight);
  200. // LogUtil.d(TAG, "drawLongPicture layout bottom view = " + bottomHeight);
  201. }
  202. /**
  203. * 绘制方法
  204. */
  205. private void drawPoster() {
  206. // 计算出最终生成的长图的高度 = 上、中、图片总高度、下等个个部分加起来
  207. int allBitmapHeight = topHeight + contentHeight + bottomHeight;
  208. // 创建空白画布
  209. Bitmap.Config config = Bitmap.Config.RGB_565;
  210. Bitmap bitmapAll = Bitmap.createBitmap(longPictureWidth, allBitmapHeight, config);
  211. Canvas canvas = new Canvas(bitmapAll);
  212. canvas.drawColor(Color.WHITE);
  213. Paint paint = new Paint();
  214. paint.setAntiAlias(true);
  215. paint.setDither(true);
  216. paint.setFilterBitmap(true);
  217. // 绘制top view
  218. Bitmap topBit = BitmapUtil.getLayoutBitmap(topViewLl, longPictureWidth, topHeight);
  219. canvas.drawBitmap(topBit, 0, 0, paint);
  220. //绘制头像
  221. Bitmap avatarBit;
  222. if (isContainAvatar) {
  223. int aWidth = (int) DimensionUtil.dp2px(77);
  224. avatarBit = BitmapUtil.resizeImage(BitmapFactory.decodeFile(localImagePathMap.get(imageUrlList.get(0))), aWidth, aWidth);
  225. } else {
  226. avatarBit = BitmapUtil.drawableToBitmap(context.getDrawable(R.drawable.placeholder));
  227. }
  228. if (avatarBit != null) {
  229. avatarBit = BitmapUtil.getOvalBitmap(avatarBit, (int) DimensionUtil.dp2px(38));
  230. canvas.drawBitmap(avatarBit, DimensionUtil.dp2px(20), DimensionUtil.dp2px(70), paint);
  231. }
  232. //绘制中间图片列表
  233. if (isContainAvatar && imageUrlList.size() > 1) {
  234. Bitmap bitmapTemp;
  235. int top = (int) (topHeight + DimensionUtil.dp2px(20));
  236. for (int i = 1; i < imageUrlList.size(); i++) {
  237. String filePath = localImagePathMap.get(imageUrlList.get(i));
  238. bitmapTemp = BitmapUtil.fitBitmap(BitmapFactory.decodeFile(filePath),
  239. longPictureWidth - leftRightMargin * 2);
  240. if (i > 1)
  241. top += imgHeightMap.get(i - 1) + DimensionUtil.dp2px(10);
  242. canvas.drawBitmap(bitmapTemp, leftRightMargin, top, paint);
  243. tempList.add(bitmapTemp);
  244. }
  245. } else if (!isContainAvatar && !imageUrlList.isEmpty()) {
  246. Bitmap bitmapTemp;
  247. int top = (int) (topHeight + DimensionUtil.dp2px(20));
  248. for (int i = 0; i < imageUrlList.size(); i++) {
  249. String filePath = localImagePathMap.get(imageUrlList.get(i));
  250. bitmapTemp = BitmapUtil.fitBitmap(BitmapFactory.decodeFile(filePath),
  251. longPictureWidth - leftRightMargin * 2);
  252. if (i > 0)
  253. top += imgHeightMap.get(i - 1) + DimensionUtil.dp2px(10);
  254. canvas.drawBitmap(bitmapTemp, leftRightMargin, top, paint);
  255. tempList.add(bitmapTemp);
  256. }
  257. }
  258. // 绘制bottom view
  259. Bitmap bottomBit = BitmapUtil.getLayoutBitmap(bottomViewFl, longPictureWidth, bottomHeight);
  260. canvas.drawBitmap(bottomBit, 0, topHeight + contentHeight, paint);
  261. // 绘制QrCode
  262. //if (qrcodeBit != null)
  263. //canvas.drawBitmap(qrcodeBit, longPictureWidth - DimensionUtil.dp2px(150),
  264. //topHeight + contentHeight + DimensionUtil.dp2px(15), paint);
  265. //保存最终的图片
  266. String time = String.valueOf(System.currentTimeMillis());
  267. boolean state = BitmapUtil.saveImage(bitmapAll, context.getExternalCacheDir() +
  268. File.separator, time, Bitmap.CompressFormat.JPEG, 80);
  269. //绘制回调
  270. if (listener != null) {
  271. if (state) {
  272. listener.onSuccess(context.getExternalCacheDir() + File.separator + time);
  273. } else {
  274. listener.onFail();
  275. }
  276. }
  277. //清空所有Bitmap
  278. tempList.add(topBit);
  279. tempList.add(avatarBit);
  280. tempList.add(bottomBit);
  281. tempList.add(bitmapAll);
  282. for (Bitmap bit : tempList) {
  283. if (bit != null && !bit.isRecycled()) {
  284. bit.recycle();
  285. }
  286. }
  287. tempList.clear();
  288. //绘制完成,删除所有保存的图片
  289. for (int i = 0; i < imageUrlList.size(); i++) {
  290. String path = localImagePathMap.get(imageUrlList.get(i));
  291. File file = new File(path);
  292. if (file.exists()) {
  293. file.delete();
  294. }
  295. }
  296. }
  297. /**
  298. * 获取当前下载所有图片的高度,忽略头像
  299. */
  300. private int getAllImageHeight() {
  301. imgHeightMap.clear();
  302. int height = 0;
  303. int startIndex = 0;
  304. int cutNum = 1;
  305. if (isContainAvatar) {
  306. cutNum = 2;
  307. startIndex = 1;
  308. }
  309. for (int i = startIndex; i < imageUrlList.size(); i++) {
  310. Bitmap tamp = BitmapUtil.fitBitmap(BitmapFactory.decodeFile(localImagePathMap.get(imageUrlList.get(i))),
  311. longPictureWidth - leftRightMargin * 2);
  312. height += tamp.getHeight();
  313. imgHeightMap.put(i, tamp.getHeight());
  314. tempList.add(tamp);
  315. }
  316. height = (int) (height + DimensionUtil.dp2px(10) * (imageUrlList.size() - cutNum));
  317. return height;
  318. }
  319. /**
  320. * 手动测量view宽高
  321. */
  322. private void layoutView(View v) {
  323. v.layout(0, 0, DoukouApplication.screenWidth, DoukouApplication.screenHeight);
  324. int measuredWidth = View.MeasureSpec.makeMeasureSpec(DoukouApplication.screenWidth, View.MeasureSpec.EXACTLY);
  325. int measuredHeight = View.MeasureSpec.makeMeasureSpec(Integer.MAX_VALUE >> 2, MeasureSpec.AT_MOST);
  326. v.measure(measuredWidth, measuredHeight);
  327. v.layout(0, 0, v.getMeasuredWidth(), v.getMeasuredHeight());
  328. }
  329. public interface Listener {
  330. /**
  331. * 生成长图成功的回调
  332. *
  333. * @param path 长图路径
  334. */
  335. void onSuccess(String path);
  336. /**
  337. * 生成长图失败的回调
  338. */
  339. void onFail();
  340. }
  341. }

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

  1. <?xml version="1.0" encoding="utf-8"?>
  2. <ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
  3. android:layout_width="match_parent"
  4. android:layout_height="match_parent">
  5. <LinearLayout
  6. android:layout_width="match_parent"
  7. android:layout_height="wrap_content"
  8. android:background="@color/white"
  9. android:orientation="vertical">
  10. <LinearLayout
  11. android:id="@+id/ll_top_view"
  12. android:layout_width="match_parent"
  13. android:layout_height="wrap_content"
  14. android:orientation="vertical"
  15. android:paddingLeft="15dp"
  16. android:paddingRight="15dp">
  17. <LinearLayout
  18. android:layout_width="wrap_content"
  19. android:layout_height="wrap_content"
  20. android:layout_gravity="center_horizontal"
  21. android:layout_marginTop="25dp"
  22. android:gravity="center_vertical"
  23. android:orientation="horizontal">
  24. <TextView
  25. android:id="@+id/app_name_tv"
  26. android:layout_width="wrap_content"
  27. android:layout_height="wrap_content"
  28. android:textColor="#fffb4e90"
  29. android:textSize="18sp" />
  30. <View
  31. android:layout_width="1dp"
  32. android:layout_height="14dp"
  33. android:layout_marginHorizontal="10dp"
  34. android:background="@color/colorPrimary" />
  35. <TextView
  36. android:layout_width="wrap_content"
  37. android:layout_height="wrap_content"
  38. android:textColor="#fffb4e90"
  39. android:textSize="18sp" />
  40. </LinearLayout>
  41. <FrameLayout
  42. android:layout_width="match_parent"
  43. android:layout_height="wrap_content"
  44. android:layout_marginTop="20dp">
  45. <TextView
  46. android:id="@+id/tv_name"
  47. android:layout_width="wrap_content"
  48. android:layout_height="wrap_content"
  49. android:layout_marginStart="87dp"
  50. android:layout_marginTop="8dp"
  51. android:textColor="@color/c33"
  52. android:textSize="18sp" />
  53. <TextView
  54. android:id="@+id/tv_course_name"
  55. android:layout_width="match_parent"
  56. android:layout_height="wrap_content"
  57. android:layout_marginStart="87dp"
  58. android:layout_marginTop="43dp"
  59. android:textColor="@color/c66"
  60. android:textSize="18sp" />
  61. </FrameLayout>
  62. <TextView
  63. android:id="@+id/tv_course_detail_name"
  64. android:layout_width="wrap_content"
  65. android:layout_height="wrap_content"
  66. android:layout_gravity="center_horizontal"
  67. android:layout_marginTop="28dp"
  68. android:background="@drawable/shape_black_radius2"
  69. android:paddingHorizontal="22dp"
  70. android:paddingVertical="10dp"
  71. android:textColor="#ffffffff"
  72. android:textSize="15sp" />
  73. </LinearLayout>
  74. <LinearLayout
  75. android:id="@+id/ll_content"
  76. android:layout_width="match_parent"
  77. android:layout_height="wrap_content"
  78. android:orientation="vertical"
  79. android:paddingLeft="15dp"
  80. android:paddingTop="20dp"
  81. android:paddingRight="15dp"
  82. android:paddingBottom="10dp" />
  83. <FrameLayout
  84. android:id="@+id/fl_bottom_view"
  85. android:layout_width="match_parent"
  86. android:layout_height="wrap_content"
  87. android:gravity="center_vertical"
  88. android:orientation="horizontal"
  89. android:paddingLeft="15dp"
  90. android:paddingRight="15dp"
  91. android:paddingBottom="20dp">
  92. <ImageView
  93. android:layout_width="match_parent"
  94. android:layout_height="150dp"
  95. android:scaleType="fitXY"
  96. android:src="@drawable/bg_qr_code" />
  97. <TextView
  98. android:id="@+id/qr_code_content_tv"
  99. android:layout_width="175dp"
  100. android:layout_height="wrap_content"
  101. android:layout_gravity="center_vertical"
  102. android:layout_marginLeft="15dp"
  103. android:ellipsize="end"
  104. android:maxLines="3"
  105. android:textColor="@color/white"
  106. android:textSize="15sp" />
  107. </FrameLayout>
  108. </LinearLayout>
  109. </ScrollView>

BitmapUtil工具类~

  1. import android.Manifest;
  2. import android.content.Context;
  3. import android.content.Intent;
  4. import android.graphics.Bitmap;
  5. import android.graphics.BitmapFactory;
  6. import android.graphics.Canvas;
  7. import android.graphics.Matrix;
  8. import android.graphics.Paint;
  9. import android.graphics.PixelFormat;
  10. import android.graphics.PorterDuff;
  11. import android.graphics.PorterDuffXfermode;
  12. import android.graphics.Rect;
  13. import android.graphics.RectF;
  14. import android.graphics.drawable.Drawable;
  15. import android.media.ExifInterface;
  16. import android.net.Uri;
  17. import android.os.Build;
  18. import android.os.Environment;
  19. import android.renderscript.Allocation;
  20. import android.renderscript.Element;
  21. import android.renderscript.RenderScript;
  22. import android.renderscript.ScriptIntrinsicBlur;
  23. import android.text.TextUtils;
  24. import android.util.Log;
  25. import android.view.View;
  26. import android.view.ViewGroup;
  27. import androidx.annotation.RequiresApi;
  28. import androidx.fragment.app.FragmentActivity;
  29. import com.tbruyelle.rxpermissions2.RxPermissions;
  30. import java.io.ByteArrayOutputStream;
  31. import java.io.File;
  32. import java.io.FileOutputStream;
  33. import java.io.IOException;
  34. import java.util.UUID;
  35. public class BitmapUtil {
  36. private static final String TAG = "BitmapUtil";
  37. /**
  38. * 将Bitmap转成图片保存本地
  39. */
  40. public static boolean saveImage(Bitmap bitmap, String filePath, String filename, Bitmap.CompressFormat format, int quality) {
  41. if (quality > 100) {
  42. Log.d("saveImage", "quality cannot be greater that 100");
  43. return false;
  44. }
  45. File file;
  46. FileOutputStream out = null;
  47. try {
  48. switch (format) {
  49. case PNG:
  50. file = new File(filePath, filename);
  51. out = new FileOutputStream(file);
  52. return bitmap.compress(Bitmap.CompressFormat.PNG, quality, out);
  53. case JPEG:
  54. file = new File(filePath, filename);
  55. out = new FileOutputStream(file);
  56. return bitmap.compress(Bitmap.CompressFormat.JPEG, quality, out);
  57. default:
  58. file = new File(filePath, filename + ".png");
  59. out = new FileOutputStream(file);
  60. return bitmap.compress(Bitmap.CompressFormat.PNG, quality, out);
  61. }
  62. } catch (Exception e) {
  63. e.printStackTrace();
  64. } finally {
  65. try {
  66. if (out != null) {
  67. out.close();
  68. }
  69. } catch (IOException e) {
  70. e.printStackTrace();
  71. }
  72. }
  73. return false;
  74. }
  75. /**
  76. * drawable 转 bitmap
  77. */
  78. public static Bitmap drawableToBitmap(Drawable drawable) {
  79. // 取 drawable 的长宽
  80. int w = drawable.getIntrinsicWidth();
  81. int h = drawable.getIntrinsicHeight();
  82. // 取 drawable 的颜色格式
  83. Bitmap.Config config = drawable.getOpacity() != PixelFormat.OPAQUE ? Bitmap.Config.ARGB_8888 : Bitmap.Config.RGB_565;
  84. // 建立对应 bitmap
  85. Bitmap bitmap = Bitmap.createBitmap(w, h, config);
  86. // 建立对应 bitmap 的画布
  87. Canvas canvas = new Canvas(bitmap);
  88. drawable.setBounds(0, 0, w, h);
  89. // 把 drawable 内容画到画布中
  90. drawable.draw(canvas);
  91. return bitmap;
  92. }
  93. public static void saveImage(FragmentActivity context, Bitmap bmp, boolean recycle) {
  94. new RxPermissions(context).request(Manifest.permission.READ_EXTERNAL_STORAGE, Manifest.permission.WRITE_EXTERNAL_STORAGE)
  95. .subscribe(granted -> {
  96. if (granted) {
  97. if (BitmapUtil.saveImageToGallery(context, bmp)) {
  98. ToastUtil.showShort(context, "保存成功");
  99. } else {
  100. ToastUtil.showShort(context, "保存失败");
  101. }
  102. } else {
  103. ToastUtil.showShort(context, "请获取存储权限");
  104. }
  105. if (recycle) bmp.recycle();
  106. });
  107. }
  108. //保存图片到指定路径
  109. private static boolean saveImageToGallery(FragmentActivity context, Bitmap bmp) {
  110. // 首先保存图片
  111. String storePath = Environment.getExternalStorageDirectory().getAbsolutePath() + File.separator +
  112. Environment.DIRECTORY_PICTURES + File.separator + "test";
  113. File appDir = new File(storePath);
  114. if (!appDir.exists()) {
  115. appDir.mkdir();
  116. }
  117. String fileName = System.currentTimeMillis() + ".jpg";
  118. File file = new File(appDir, fileName);
  119. try {
  120. FileOutputStream fos = new FileOutputStream(file);
  121. //通过io流的方式来压缩保存图片
  122. boolean isSuccess = bmp.compress(Bitmap.CompressFormat.JPEG, 60, fos);
  123. fos.flush();
  124. fos.close();
  125. //把文件插入到系统图库
  126. // MediaStore.Images.Media.insertImage(context.getContentResolver(), bmp, fileName, null);
  127. //保存图片后发送广播通知更新数据库
  128. Intent intent = new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE);
  129. Uri uri = Uri.fromFile(new File(file.getAbsolutePath()));
  130. LogUtil.e("路径============", file.getAbsolutePath());
  131. intent.setData(uri);
  132. context.sendBroadcast(intent);
  133. return isSuccess;
  134. } catch (IOException e) {
  135. e.printStackTrace();
  136. }
  137. return false;
  138. }
  139. public static String getImgFilePath() {
  140. String storePath = Environment.getExternalStorageDirectory().getAbsolutePath() + File.separator +
  141. Environment.DIRECTORY_PICTURES + File.separator + "test" + File.separator;
  142. File appDir = new File(storePath);
  143. if (!appDir.exists()) {
  144. appDir.mkdir();
  145. }
  146. return storePath + UUID.randomUUID().toString().replace("-", "") + ".jpg";
  147. }
  148. /***
  149. * 得到指定半径的圆形Bitmap
  150. * @param bitmap 图片
  151. * @param radius 半径
  152. * @return bitmap
  153. */
  154. public static Bitmap getOvalBitmap(Bitmap bitmap, int radius) {
  155. Bitmap output = Bitmap.createBitmap(bitmap.getWidth(), bitmap
  156. .getHeight(), Bitmap.Config.ARGB_8888);
  157. Canvas canvas = new Canvas(output);
  158. int width = bitmap.getWidth();
  159. int height = bitmap.getHeight();
  160. float scaleWidth = ((float) 2 * radius) / width;
  161. Matrix matrix = new Matrix();
  162. matrix.postScale(scaleWidth, scaleWidth);
  163. bitmap = Bitmap.createBitmap(bitmap, 0, 0, width, height, matrix, true);
  164. final int color = 0xff424242;
  165. final Paint paint = new Paint();
  166. final Rect rect = new Rect(0, 0, bitmap.getWidth(), bitmap.getHeight());
  167. final RectF rectF = new RectF(rect);
  168. paint.setAntiAlias(true);
  169. canvas.drawARGB(0, 0, 0, 0);
  170. paint.setColor(color);
  171. canvas.drawOval(rectF, paint);
  172. paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN));
  173. canvas.drawBitmap(bitmap, rect, rect, paint);
  174. return output;
  175. }
  176. /**
  177. * layout布局转Bitmap
  178. *
  179. * @param layout 布局
  180. * @param w 宽
  181. * @param h 高
  182. * @return bitmap
  183. */
  184. public static Bitmap getLayoutBitmap(ViewGroup layout, int w, int h) {
  185. Bitmap originBitmap = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);
  186. Canvas canvas = new Canvas(originBitmap);
  187. layout.draw(canvas);
  188. return resizeImage(originBitmap, w, h);
  189. }
  190. public static Bitmap resizeImage(Bitmap origin, int newWidth, int newHeight) {
  191. if (origin == null) {
  192. return null;
  193. }
  194. int height = origin.getHeight();
  195. int width = origin.getWidth();
  196. float scaleWidth = ((float) newWidth) / width;
  197. float scaleHeight = ((float) newHeight) / height;
  198. Matrix matrix = new Matrix();
  199. matrix.postScale(scaleWidth, scaleHeight);
  200. Bitmap newBM = Bitmap.createBitmap(origin, 0, 0, width, height, matrix, false);
  201. if (!origin.isRecycled()) {
  202. origin.recycle();
  203. }
  204. return newBM;
  205. }
  206. /**
  207. * fuction: 设置固定的宽度,高度随之变化,使图片不会变形
  208. *
  209. * @param target 需要转化bitmap参数
  210. * @param newWidth 设置新的宽度
  211. * @return
  212. */
  213. public static Bitmap fitBitmap(Bitmap target, int newWidth) {
  214. int width = target.getWidth();
  215. int height = target.getHeight();
  216. Matrix matrix = new Matrix();
  217. float scaleWidth = ((float) newWidth) / width;
  218. // float scaleHeight = ((float)newHeight) / height;
  219. int newHeight = (int) (scaleWidth * height);
  220. matrix.postScale(scaleWidth, scaleWidth);
  221. // Bitmap result = Bitmap.createBitmap(target,0,0,width,height,
  222. // matrix,true);
  223. Bitmap bmp = Bitmap.createBitmap(target, 0, 0, width, height, matrix,
  224. true);
  225. if (target != null && !target.equals(bmp) && !target.isRecycled()) {
  226. target.recycle();
  227. target = null;
  228. }
  229. return bmp;// Bitmap.createBitmap(target, 0, 0, width, height, matrix,
  230. // true);
  231. }
  232. }

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

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/我家小花儿/article/detail/262077
推荐阅读
相关标签
  

闽ICP备14008679号