当前位置:   article > 正文

Android实现将View转化为图片并保存到本地_android view to image

android view to image

一、概述

app中有需求需要将View转化为图片并保存到本地,这里分两种情况: 
1.View本身已经显示在界面上 
2.View还没有添加到界面上或者没有显示(绘制)过

二、实现方法

对于上述的第一种情况我使用下面代码即可:

  1. private void viewSaveToImage(View view) {
  2.         view.setDrawingCacheEnabled(true);
  3.         view.setDrawingCacheQuality(View.DRAWING_CACHE_QUALITY_HIGH);
  4.         view.setDrawingCacheBackgroundColor(Color.WHITE);
  5.         // 把一个View转换成图片
  6.         Bitmap cachebmp = loadBitmapFromView(view);
  7.         FileOutputStream fos;
  8.         String imagePath = "";
  9.         try {
  10.             // 判断手机设备是否有SD卡
  11.             boolean isHasSDCard = Environment.getExternalStorageState().equals(
  12.                     android.os.Environment.MEDIA_MOUNTED);
  13.             if (isHasSDCard) {
  14.                 // SD卡根目录
  15.                 File sdRoot = Environment.getExternalStorageDirectory();
  16.                 File file = new File(sdRoot, Calendar.getInstance().getTimeInMillis()+".png");
  17.                 fos = new FileOutputStream(file);
  18.                 imagePath = file.getAbsolutePath();
  19.             } else
  20.                 throw new Exception("创建文件失败!");
  21.             cachebmp.compress(Bitmap.CompressFormat.PNG, 90, fos);
  22.             fos.flush();
  23.             fos.close();
  24.         } catch (Exception e) {
  25.             e.printStackTrace();
  26.         }
  27.         LogUtil.e("imagePath="+imagePath);
  28.         view.destroyDrawingCache();
  29.     }
  30.     private Bitmap loadBitmapFromView(View v) {
  31.         int w = v.getWidth();
  32.         int h = v.getHeight();
  33.         Bitmap bmp = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);
  34.         Canvas c = new Canvas(bmp);
  35.         c.drawColor(Color.WHITE);
  36.         /** 如果不设置canvas画布为白色,则生成透明 */
  37.         v.layout(0, 0, w, h);
  38.         v.draw(c);
  39.         return bmp;
  40.     }

也可以按下面做:

  1. public static Bitmap getBitmapByView(ScrollView scrollView) {
  2. int h = 0;
  3. Bitmap bitmap = null;
  4. for (int i = 0; i < scrollView.getChildCount(); i++) {
  5. h += scrollView.getChildAt(i).getHeight();
  6. }
  7. bitmap = Bitmap.createBitmap(scrollView.getWidth(), h,
  8. Bitmap.Config.RGB_565);
  9. final Canvas canvas = new Canvas(bitmap);
  10. scrollView.draw(canvas);
  11. return bitmap;
  12. }

满足layout生成bitmap,然后bitmap可以再生成图片

  1. public static void savePhotoToSDCard(Bitmap photoBitmap, String path, String photoName) {
  2. if (checkSDCardAvailable()) {
  3. File dir = new File(path);
  4. if (!dir.exists()) {
  5. dir.mkdirs();
  6. }
  7. File photoFile = new File(path, photoName + ".png");
  8. FileOutputStream fileOutputStream = null;
  9. try {
  10. fileOutputStream = new FileOutputStream(photoFile);
  11. if (photoBitmap != null) {
  12. if (photoBitmap.compress(Bitmap.CompressFormat.PNG, 100, fileOutputStream)) {
  13. fileOutputStream.flush();
  14. }
  15. }
  16. } catch (FileNotFoundException e) {
  17. photoFile.delete();
  18. e.printStackTrace();
  19. } catch (IOException e) {
  20. photoFile.delete();
  21. e.printStackTrace();
  22. } finally {
  23. try {
  24. fileOutputStream.close();
  25. } catch (IOException e) {
  26. e.printStackTrace();
  27. }
  28. }
  29. }
  30. }

检查是否有SD卡

 

  1. public static boolean checkSDCardAvailable() {
  2.         return android.os.Environment.getExternalStorageState().equals(android.os.Environment.MEDIA_MOUNTED);
  3. }



用例:

 

  1. Bitmap bitmap = getBitmapByView(contentLly);//contentLly是布局文件                   
  2.  ImageUtils.savePhotoToSDCard(bitmap, "/sdcard/test", "test");

 

如果是第二种,还这样使用的话,就会报错了,因为View在添加到容器中之前并没有得到实际的大小,所以首先需要指定View的大小:

  1. DisplayMetrics metric = new DisplayMetrics();
  2.                     getWindowManager().getDefaultDisplay().getMetrics(metric);
  3.                     int width = metric.widthPixels;     // 屏幕宽度(像素)
  4.                     int height = metric.heightPixels;   // 屏幕高度(像素)
  5.                     View mingpianView = LayoutInflater.from(this).inflate(R.layout.view_team_mingpian, null, false);
  6.                     layoutView(mingpianView, width, height);



//然后View和其内部的子View都具有了实际大小,也就是完成了布局,相当与添加到了界面上。接着就可以创建位图并在上面绘制了:

  1. private void layoutView(View v, int width, int height) {
  2. // 指定整个View的大小 参数是左上角 和右下角的坐标
  3. v.layout(0, 0, width, height);
  4. int measuredWidth = View.MeasureSpec.makeMeasureSpec(width, View.MeasureSpec.EXACTLY);
  5. int measuredHeight = View.MeasureSpec.makeMeasureSpec(height, View.MeasureSpec.AT_MOST);
  6. /** 当然,measure完后,并不会实际改变View的尺寸,需要调用View.layout方法去进行布局。
  7. * 按示例调用layout函数后,View的大小将会变成你想要设置成的大小。
  8. */
  9. v.measure(measuredWidth, measuredHeight);
  10. v.layout(0, 0, v.getMeasuredWidth(), v.getMeasuredHeight());
  11. }

在int measuredHeight = View.MeasureSpec.makeMeasureSpec(height, View.MeasureSpec.AT_MOST); 

这里我有点不懂后面函数的取值。在自定义view里onMeasure()里有根据MeasureSpec.getMode()的类型来准确得到设置view的长宽

.makeMeasureSpec(height, View.MeasureSpec.AT_MOST);却貌似取了 自适应和前一个int参数的最小值。

后面我发现有可能合成出超出屏幕的长图,就直接吧前一个int参数赋值成一个很大的数字。。。

MainActivity

  1. public class MainActivity extends Activity {
  2. ImageView aaa ;
  3. @Override
  4. protected void onCreate(Bundle savedInstanceState) {
  5. super.onCreate(savedInstanceState);
  6. setContentView(R.layout.activity_main);
  7. DisplayMetrics metric = new DisplayMetrics();
  8. getWindowManager().getDefaultDisplay().getMetrics(metric);
  9. int width = metric.widthPixels; // 屏幕宽度(像素)
  10. int height = metric.heightPixels; // 屏幕高度(像素)
  11. View view = LayoutInflater.from(this).inflate(R.layout.view_photo, null, false);
  12. layoutView(view, width, height);
  13. final ScrollView tv = (ScrollView) view.findViewById(R.id.textView);
  14. aaa = (ImageView) findViewById(R.id.aaa);
  15. final Runnable runnable = new Runnable() {
  16. @Override
  17. public void run() {
  18. viewSaveToImage(tv);
  19. }
  20. };
  21. Button button = (Button) findViewById(R.id.button);
  22. button.setOnClickListener(new View.OnClickListener() {
  23. @Override
  24. public void onClick(View v) {
  25. new Handler().post(runnable);
  26. }
  27. });
  28. }
  29. //然后View和其内部的子View都具有了实际大小,也就是完成了布局,相当与添加到了界面上。接着就可以创建位图并在上面绘制了:
  30. private void layoutView(View v, int width, int height) {
  31. // 整个View的大小 参数是左上角 和右下角的坐标
  32. v.layout(0, 0, width, height);
  33. int measuredWidth = View.MeasureSpec.makeMeasureSpec(width, View.MeasureSpec.EXACTLY);
  34. int measuredHeight = View.MeasureSpec.makeMeasureSpec(10000, View.MeasureSpec.AT_MOST);
  35. /** 当然,measure完后,并不会实际改变View的尺寸,需要调用View.layout方法去进行布局。
  36. * 按示例调用layout函数后,View的大小将会变成你想要设置成的大小。
  37. */
  38. v.measure(measuredWidth, measuredHeight);
  39. v.layout(0, 0, v.getMeasuredWidth(), v.getMeasuredHeight());
  40. }
  41. public void viewSaveToImage(View view) {
  42. Log.e("ssh","a");
  43. /**
  44. * View组件显示的内容可以通过cache机制保存为bitmap
  45. * 我们要获取它的cache先要通过setDrawingCacheEnable方法把cache开启,
  46. * 然后再调用getDrawingCache方法就可 以获得view的cache图片了
  47. * 。buildDrawingCache方法可以不用调用,因为调用getDrawingCache方法时,
  48. * 若果 cache没有建立,系统会自动调用buildDrawingCache方法生成cache。
  49. * 若果要更新cache, 必须要调用destoryDrawingCache方法把旧的cache销毁,才能建立新的。
  50. */
  51. // view.setDrawingCacheEnabled(true);
  52. // view.setDrawingCacheQuality(View.DRAWING_CACHE_QUALITY_HIGH);
  53. //设置绘制缓存背景颜色
  54. // view.setDrawingCacheBackgroundColor(Color.WHITE);
  55. // 把一个View转换成图片
  56. Bitmap cachebmp = loadBitmapFromView(view);
  57. aaa.setImageBitmap(cachebmp);//直接展示转化的bitmap
  58. //保存在本地 产品还没决定要不要保存在本地
  59. FileOutputStream fos;
  60. try {
  61. // 判断手机设备是否有SD卡
  62. boolean isHasSDCard = Environment.getExternalStorageState().equals(
  63. android.os.Environment.MEDIA_MOUNTED);
  64. if (isHasSDCard) {
  65. // SD卡根目录
  66. File sdRoot = Environment.getExternalStorageDirectory();
  67. Log.e("ssh",sdRoot.toString());
  68. File file = new File(sdRoot, "test.png");
  69. fos = new FileOutputStream(file);
  70. } else
  71. throw new Exception("创建文件失败!");
  72. //压缩图片 30 是压缩率,表示压缩70%; 如果不压缩是100,表示压缩率为0
  73. cachebmp.compress(Bitmap.CompressFormat.PNG, 90, fos);
  74. fos.flush();
  75. fos.close();
  76. } catch (Exception e) {
  77. e.printStackTrace();
  78. }
  79. view.destroyDrawingCache();
  80. }
  81. private Bitmap loadBitmapFromView(View v) {
  82. int w = v.getWidth();
  83. int h = v.getHeight();
  84. Bitmap bmp = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);
  85. Canvas c = new Canvas(bmp);
  86. c.drawColor(Color.WHITE);
  87. /** 如果不设置canvas画布为白色,则生成透明 */
  88. v.layout(0, 0, w, h);
  89. v.draw(c);
  90. return bmp;
  91. }
  92. }

参考:

 

https://blog.csdn.net/qq_16247851/article/details/72772370

https://blog.csdn.net/shallcheek/article/details/46998643

https://blog.csdn.net/a450479378/article/details/53081814

https://blog.csdn.net/chenzheng8975/article/details/76206290

 

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

闽ICP备14008679号