产品今天说项目分享时要分享出一张  封面图片 + 几行文字 + 二维码图片 的图片。

思索了一下 封面图片和二维码图片让后台给接口得到地址, 主要还是找个方式得到一个包含这些内容的图片。于是就想能不能将View转化成bitmap对象

然后就走了一遍各个前辈的路 整理了下原理和思路。

根据产品的需求  我要实现的步骤  把所有需要的集合在一个View里 —— View转化成bitmap —— 分享出去(第三方分享bitmap对象)

接着搞个demo 实验一下

要转化的view 大致长这样

view_photo.xml

  1. <?xml version="1.0" encoding="utf-8"?>
  2. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
  3. android:layout_width="match_parent"
  4. android:layout_height="match_parent"
  5. android:orientation="vertical" >
  6. <ScrollView
  7. android:id="@+id/textView"
  8. android:layout_width="match_parent"
  9. android:layout_height="match_parent" >
  10. <LinearLayout
  11. android:layout_width="match_parent"
  12. android:layout_height="match_parent"
  13. android:orientation="vertical" >
  14. <!--封面图片  -->
  15. <ImageView
  16. android:layout_width="400dp"
  17. android:layout_height="400dp"
  18. android:background="@drawable/ic_launcher"
  19. android:layout_gravity="center_horizontal" />
  20. <TextView
  21. android:layout_width="wrap_content"
  22. android:layout_height="wrap_content"
  23. android:text="文字 文字"
  24. android:layout_gravity="center_horizontal" />
  25. <Button
  26. android:id="@+id/button"
  27. android:layout_width="wrap_content"
  28. android:layout_height="wrap_content"
  29. android:text="假装是二维码图片"
  30. android:layout_gravity="center_horizontal" />
  31. </LinearLayout>
  32. </ScrollView>
  33. </LinearLayout>

最关键的View转bitmap

好像是有两种方法

DrawingCache方法:
如果使用DrawingCache,则对要截图的View有一个要求:View本身已经显示在界面上。如果View没有添加到界面上或者没有显示(绘制)过,则buildDrawingCache会失败。这种方式比较适合对应用界面或者某一部分的截图。步骤很简单:
  1. view.setDrawingCacheEnabled(true);
  2. view.buildDrawingCache();  //启用DrawingCache并创建位图
  3. Bitmap bitmap = Bitmap.createBitmap(view.getDrawingCache()); //创建一个DrawingCache的拷贝,因为DrawingCache得到的位图在禁用后会被回收
  4. view.setDrawingCacheEnabled(false);  //禁用DrawingCahce否则会影响性能
View.draw方法:
这个也很简单 view对象传进去.draw()就行
  1. private Bitmap loadBitmapFromView(View v) {
  2. int w = v.getWidth();
  3. int h = v.getHeight();
  4. Bitmap bmp = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);
  5. Canvas c = new Canvas(bmp);
  6. c.drawColor(Color.WHITE);
  7. /** 如果不设置canvas画布为白色,则生成透明 */
  8. v.layout(0, 0, w, h);
  9. v.draw(c);
  10. return bmp;
  11. }
然而此时适用于需要截图的View并没有添加到界面上,
可能是通过java代码创建的或者inflate创建的,(我需求的情况就适用于这种。分享的时候生成bitmap对象但不显示在界面中)
此时调用DrawingCache方法是获取不到位图的。
因为View在添加到容器中之前并没有得到实际的大小(如果LayoutWidth是MatchParent,它还没有Parent…)
,所以首先需要指定View的大小:
先得到
  1. DisplayMetrics metric = new DisplayMetrics();
  2. getWindowManager().getDefaultDisplay().getMetrics(metric);
  3. int width = metric.widthPixels;     // 屏幕宽度(像素)
  4. int height = metric.heightPixels;   // 屏幕高度(像素)
  5. View view = LayoutInflater.from(this).inflate(R.layout.view_photo, null, false);
  6. layoutView(view, width, height);//去到指定view大小的函数
  1. //然后View和其内部的子View都具有了实际大小,也就是完成了布局,相当与添加到了界面上。接着就可以创建位图并在上面绘制了:
  2. private void layoutView(View v, int width, int height) {
  3. // 指定整个View的大小 参数是左上角 和右下角的坐标
  4. v.layout(0, 0, width, height);
  5. int measuredWidth = View.MeasureSpec.makeMeasureSpec(width, View.MeasureSpec.EXACTLY);
  6. int measuredHeight = View.MeasureSpec.makeMeasureSpec(height, View.MeasureSpec.AT_MOST);
  7. /** 当然,measure完后,并不会实际改变View的尺寸,需要调用View.layout方法去进行布局。
  8. * 按示例调用layout函数后,View的大小将会变成你想要设置成的大小。
  9. */
  10. v.measure(measuredWidth, measuredHeight);
  11. v.layout(0, 0, v.getMeasuredWidth(), v.getMeasuredHeight());
  12. }

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

这里我有点不懂后面函数的取值。在自定义view里onMeasure()里有根据MeasureSpec.getMode()的类型来准确得到设置view的长宽
.makeMeasureSpec(height, View.MeasureSpec.AT_MOST);却貌似取了 自适应和前一个int参数的最小值。
后面我发现有可能合成出超出屏幕的长图,就直接吧前一个int参数赋值成一个很大的数字。。。
 
 
上整个demo的代码
activity_main.xml
  1. <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
  2. xmlns:tools="http://schemas.android.com/tools"
  3. android:layout_width="match_parent"
  4. android:layout_height="match_parent"
  5. tools:context="com.example.aa.MainActivity" >
  6. <Button
  7. android:id="@+id/button"
  8. android:layout_width="wrap_content"
  9. android:layout_height="wrap_content"
  10. android:text=" button" />
  11. <ImageView
  12. android:id="@+id/aaa"
  13. android:layout_below="@+id/button"
  14. android:layout_width="wrap_content"
  15. android:layout_height="wrap_content"
  16. />
  17. </RelativeLayout>

view_photo.xml 在上面

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. }

demo转化成结果的bitmap和图片

关于View转化成bitmap保存成图片的更多相关文章

  1. BitmapUtil【缩放bitmap以及将bitmap保存成图片到SD卡中】

    版权声明:本文为HaiyuKing原创文章,转载请注明出处! 前言 用于缩放bitmap以及将bitmap保存成图片到SD卡中 效果图 代码分析 bitmapZoomByHeight(Bitmap s ...

  2. 如何把Excel中的单元格等对象保存成图片

    对于Excel中的很多对象,比如单元格(Cell),图形(shape),图表(chart)等等,有时需要将它们保存成一张图片.就像截图一样. 最近做一个Excel相关的项目,项目中遇到一个很变态的需求 ...

  3. OpenGL中的深度、深度缓存、深度测试及保存成图片

    1.深度 所谓深度,就是在openGL坐标系中,像素点Z坐标距离摄像机的距离.摄像机可能放在坐标系的任何位置,那么,就不能简单的说Z数值越大或越小,就是越靠近摄像机. 2.深度缓冲区 深度缓冲区原理就 ...

  4. javacpp-opencv图像处理之1:实时视频添加文字水印并截取视频图像保存成图片,实现文字水印的字体、位置、大小、粗度、翻转、平滑等操作

    欢迎大家积极开心的加入讨论群 群号:371249677 (点击这里进群) javaCV图像处理系列: javaCV图像处理之1:实时视频添加文字水印并截取视频图像保存成图片,实现文字水印的字体.位置. ...

  5. 修改css的(屏蔽)overflow: hidden;实现浏览器能把网页全图保存成图片

    摘要: 1.项目需要,需要对网页内容“下载”保存成全图片 2.QQ浏览器等主流浏览器都支持这种下载保存功能 3.项目需要场景:编写好的项目维护文档,放在服务器上.如果是txt不能带图片可视化,如果wo ...

  6. Java 将 PPT 形状(表格、文本框、心形、图表等)保存成图片

    MS PowerPoint中的表格.文本框.心形.图表.图片等均可以称为形状,将这些形状保存成图片,便可分类储存,方便日后查找,再利用. 本文将介绍如何使用 Spire.Presentation fo ...

  7. 如何实现批量截取整个网页完整长截图,批量将网页保存成图片web2pic/webshot/screencapture/html2picture

    如何实现批量截取整个网页完整长截图,批量将网页保存成图片web2pic/webshot/screencapture [困扰?疑问?]: 您是否正受到:如何将网页保存为图片的困扰?网页很高很长截图截不全 ...

  8. c# 将byte数组保存成图片

    将byte数组保存成图片: 方式一:System.IO.File.WriteAllBytes(@"c:\test.jpg", bytes); 方式二:MemoryStream ms ...

  9. MVC下 把数据库中的byte[]值保存成图片,并显示在view页面

    MVC下 把数据库中的byte[]值转成图片,并显示在view页面 controller中的action方法 //显示图片[AllowAnonymous]public ActionResult Sho ...

随机推荐

  1. Codevs 3111 CYD啃骨头

    时间限制: 1 s   空间限制: 128000 KB   题目等级 : 黄金 Gold 题目描述 Description: CYD吃饭时有N个骨头可以啃,但CYD要午睡了,所以他只有M分钟吃饭,已知 ...

  2. 【HDOJ5978】To begin or not to begin(概率)

    题意:有k个黑球和1个红球,两个轮流抽,抽到红球算赢,问先手赢的概率大还是后手大还是相等 k<=1e5 思路:手算前几项概率 大胆猜想 #include<cstdio> #inclu ...

  3. 【Codevs1227】方格取数2(费用流)

    题意:给出一个n*n的矩阵,每一格有一个非负整数Aij,(Aij <= 1000) 现在从(1,1)出发,可以往右或者往下走,最后到达(n,n),每达到一格,把该格子的数取出来,该格子的数就变成 ...

  4. 【黑科技】读写优化 orz bdd

    转自 bdd :http://www.cnblogs.com/kevince/p/3924688.html 读入优化: inline int read() { char ch; bool flag = ...

  5. R语言入门视频笔记--5--自定义函数

    自定义函数 你可以输出一段代码,创建一个你自己定义的函数 蛋是如果你两个自定义函数的名字重复的话,后面的会把前面的替换掉 举个栗子: hanshu1 <- function(x)  sqrt(v ...

  6. Java开发笔记(一百零一)通过加解锁避免资源冲突

    前面介绍了如何通过线程同步来避免多线程并发的资源冲突问题,然而添加synchronized的方式只在简单场合够用,在一些高级场合就暴露出它的局限性,包括但不限于下列几点:1.synchronized必 ...

  7. Linux使用screen实现关闭ssh连接的情况下,让程序继续在后台运行

    Ubuntu默认没有安装screen,需要手动安装. 安装命令: sudo apt-get install screen 简单的操作方法: 直接输入命令 screen 进入screen子界面,此时pu ...

  8. Go -- 并发编程的两种限速方法

    引子 golang提供了goroutine快速实现并发编程,在实际环境中,如果goroutine中的代码要消耗大量资源时(CPU.内存.带宽等),我们就需要对程序限速,以防止goroutine将资源耗 ...

  9. postgresql 导出建表语句的方法-类似describe table

    https://www.youtube.com/watch?v=PMfcsYzj-9M  这个视频不错, The Definitive Guide to Object-Oriented JavaScr ...

  10. chrome插件网站

    chrome插件网站 http://chromecj.com/