layout转Bitmap
业务需求详细描述:最近产品说要在分享的商品图中添加一些其他图片和文字,然后拼接为一张图片,再分享到微信朋友圈,于是我就一脸懵逼了,但是没办法还是得做额!
然后整理了一下思路,主要有这么两条路线:
- 自己手动绘制。
- 将布局转换为图片。
很显然第一种方式是不合适的,无论是开发前还是开发后,成本都很大,所以果断选择了第二种方式。
一开始的时候,我没有经过大脑思考,果断的使用了getDrawingCache这个方法来解决这个业务需求,大致流程如下:
(1)创建需要显示成图片的布局,代码如下:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/picmontage_root"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="1"
android:background="@android:color/white">
<ImageView
android:id="@+id/img_shop"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_margin="20dp" />
<RelativeLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_centerHorizontal="true"
android:layout_marginBottom="20dp">
<ImageView
android:id="@+id/img_price"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
<TextView
android:id="@+id/txt_price"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true" />
</RelativeLayout>
</RelativeLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@android:color/white">
<ImageView
android:id="@+id/img_qrcode"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="20dp" />
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="20dp"
android:layout_marginRight="20dp"
android:layout_marginTop="20dp"
android:orientation="vertical">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="黄老五 提子味皇式烤芙条 300g 沙琪玛 休闲办公室零食...\n"
android:textColor="@android:color/black" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="长按识别二维码或扫一扫购买\n"
android:textColor="@android:color/darker_gray" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="From 萌店"
android:textColor="@android:color/darker_gray" />
</LinearLayout>
</LinearLayout>
</LinearLayout>
(2)设置图片和文字信息,这里为了方便,直接把文字放到了布局中,设置图片的代码如下所示:
private void addLinearLayout() {
view = View.inflate(this, R.layout.activity_picmontage, null);
LinearLayout picmontageRoot = (LinearLayout) view.findViewById(R.id.picmontage_root);
ImageView shopImg = (ImageView) view.findViewById(R.id.img_shop);
ImageView priceImg = (ImageView) view.findViewById(R.id.img_price);
TextView priceTxt = (TextView) view.findViewById(R.id.txt_price);
ImageView qrcodeImg = (ImageView) view.findViewById(R.id.img_qrcode);
shopImg.setImageResource(R.mipmap.shop);
priceImg.setImageResource(R.mipmap.price);
priceTxt.setText("$ 20.00");
priceTxt.setTextSize(20);
priceTxt.setTextColor(Color.WHITE);
qrcodeImg.setImageResource(R.mipmap.qrcode);
addViewContent.addView(view);
}
(3)然后就可以将布局转换成图片了,代码如下所示:
private void drawingCacheShow() {
Bitmap cacheBitmap = convertViewToBitmap(addViewContent);
//Bitmap cacheBitmap = getMagicDrawingCache(addViewContent);
//addViewContent.removeView(view);
if(cacheBitmap != null) {
Bitmap newBitmap = Bitmap.createBitmap(cacheBitmap);
if (newBitmap != null) {
imgAddViewCache.setImageBitmap(newBitmap);
} else {
Log.i("123", "newBitmap=null");
}
} else {
Log.i("123", "cacheBitmap=null");
}
}
public static Bitmap convertViewToBitmap(View view){
view.measure(
View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED),
View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED));
view.layout(0, 0, view.getMeasuredWidth(), view.getMeasuredHeight());
view.buildDrawingCache();
Bitmap bitmap = view.getDrawingCache();
if (bitmap != null) {
Bitmap.Config cfg = bitmap.getConfig();
Log.d("123", "----------------------- cache.getConfig() = " + cfg);
}
return bitmap;
}
(4)然后发现图片不能正确显示,经过debug之后发现原来是图片过大的缘故,一脸懵逼,虽然使用了这样的压缩算法,但总是不尽如人意:
private void addLinearLayout() {
view = View.inflate(this, R.layout.activity_picmontage, null);
LinearLayout picmontageRoot = (LinearLayout) view.findViewById(R.id.picmontage_root);
ImageView shopImg = (ImageView) view.findViewById(R.id.img_shop);
ImageView priceImg = (ImageView) view.findViewById(R.id.img_price);
TextView priceTxt = (TextView) view.findViewById(R.id.txt_price);
ImageView qrcodeImg = (ImageView) view.findViewById(R.id.img_qrcode);
// 压缩shop
Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.mipmap.shop);
shopImg.setImageBitmap(resizeBm(bitmap, 600));
priceImg.setImageResource(R.mipmap.price);
priceTxt.setText("$ 20.00");
priceTxt.setTextSize(20);
priceTxt.setTextColor(Color.WHITE);
qrcodeImg.setImageResource(R.mipmap.qrcode);
addViewContent.addView(view);
}
private Bitmap resizeBm(Bitmap bitmap, int scaleWidth) {
// 原始宽高
float rawWidth = bitmap.getWidth();
float rawHeight = bitmap.getHeight();
// 新宽高
float newWidth = 0;
float newHeight = 0;
// 将宽度缩放到scaleWidth
if(rawWidth>scaleWidth) {
newWidth = scaleWidth;
newHeight = rawHeight*(scaleWidth/rawWidth);
} else {
newWidth = rawWidth;
newHeight = rawHeight;
}
// 计算缩放比例
float widthScale = newWidth/rawWidth;
float heightScale = newHeight/rawHeight;
Log.i("123", "widthScale="+widthScale+", heightScale="+heightScale);
// 显示
Matrix matrix = new Matrix();
matrix.postScale(widthScale,heightScale);
Bitmap resizeBmp = Bitmap.createBitmap(bitmap,0,0,bitmap.getWidth(),bitmap.getHeight(),matrix,true);
return resizeBmp;
}
之后有了大神的帮助,终于顿悟了,发现了神奇的方法:view.draw(canvas)。然后就很简单了:
这里的第1步和第2步流程与上面的1、2步流程一模一样,我们直接进入第3步,我先给出主界面中的布局:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/main_root"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<ScrollView
android:layout_width="match_parent"
android:layout_height="wrap_content">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<Button
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:onClick="showPic"
android:text="显示绘制的图片" />
<ImageView
android:id="@+id/img"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<LinearLayout
android:id="@+id/main_content"
android:visibility="invisible"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"/>
</LinearLayout>
</ScrollView>
</LinearLayout>
(3)然后将该布局添加到主界面中,并设置为invisible,但不能设置为gone,否则不能成功渲染,同样不能生成图片了:
mainContent.addView(v);
(4)最后我们就可以在点击事件里面将布局生成图片了,代码如下:
public void showPic(View view) {
int width = picmontageRoot.getMeasuredWidth();
int height = picmontageRoot.getMeasuredHeight();
Bitmap b = Bitmap.createBitmap(width, height, Bitmap.Config.RGB_565);
Canvas canvas = new Canvas(b);
picmontageRoot.draw(canvas);
img.setImageBitmap(b);
}
layout转Bitmap的更多相关文章
- Android -- Drawable与Bitmap测试
Drawable 以下这个是测试加载10 ...
- Drawable与Bitmap(转)
Drawable 以下这个是测试加载10 ...
- Drawable与Bitmap 自定义
Drawable简介 Drawable是Android平下通用的图形对象,它可以装载常用格式的图像,比如GIF.PNG.JPG,当然也支持BMP.相比于View,我们并不需要去考虑如何measure. ...
- Bitmap添加水印效果
package com.loaderman.customviewdemo; import android.app.Activity; import android.graphics.Bitmap; i ...
- Bitmap之getPixel和setPixel函数
package com.loaderman.customviewdemo; import android.app.Activity; import android.graphics.Bitmap; i ...
- Bitmap之getDensity和setDensity函数
package com.loaderman.customviewdemo; import android.app.Activity; import android.graphics.Bitmap; i ...
- Android Studio配置OpenCV(非NDK)
参考:http://www.cnblogs.com/tail/p/4618476.html 工具: 1,Android Studio(AS)1.4 2,Opencv 2.4.11 步骤: 1,解压下载 ...
- android中的图片处理
大图片处理 大图片处理是将原来像素高的转换为像素低的图片,比如原来图片是1024*768的,而手机屏幕是800*600的,这时候就需要进行转换.转换的方式很简单就是等比例缩放. package xid ...
- Android开发之多媒体编程之获取图片的副本
使用BitmapFactory的decodeFile()方法获取的Bitmap对象是只读的,无法进行编辑操作 需要进行编辑的话,需要获取到该对象的一个副本 代码如下: import android.a ...
随机推荐
- Could not load file or assembly 'MyAssembly.XmlSerializers
https://stackoverflow.com/questions/17755559/could-not-load-file-or-assembly-myassembly-xmlserialize ...
- Oracle:不同数据库版本导致的Ora-00918问题
今天有同事反映,一个sql在10.0.2.4下面执行是好的,在11.0.2.3报Ora-00918问题. sql语句如下: SELECT kcdm, bjdm, f.kszc, f.jszc FROM ...
- oracle:对Index重建、分析
对index进行分析,index_stats 表很有用.下面例子就结合index相关操作及 index_stats 的使用,对index进行分析. SQL> select count(*) fr ...
- 书写优雅的shell脚本(三) - shell中exec解析
参考:<linux命令.编辑器与shell编程> <unix环境高级编程> exec和source都属于bash内部命令(builtins commands),在bash下输入 ...
- Android studio 构建太慢
/*********************************************************************************** * Android studi ...
- [Selenium] HTML5 中的 Geolocation
在 HTML5 ,新特性 Geolocation 用于定位用户位置信息. 由于用户位置信息是敏感信息,所以需要得到用户允许后,才能让程序通过 API 获取当前用户信息.WebDriver 程序每次重 ...
- javascript之表格节点操作
<html> <div class='add'> 名字: <input type="" name=""&g ...
- MongoDB之shard_副本集和分片部署
机器角色分配和拓扑环境如下: -------------------配置副本集s1-------------------------------1.创建目录在s1h1上创建如下目录[root@node ...
- 如何在Centos7上安装&使用docker
Docker 是一个开源工具,它可以让创建和管理 Linux 容器变得简单.容器就像是轻量级的虚拟机,并且可以以毫秒级的速度来启动或停止.Docker 帮助系统管理员和程序员在容器中开发应用程序,并且 ...
- CClientDC类 CWindowDC类
CClientDC类 CClientDC类也是CDC类的派生类.它只能在窗口的客户区(即窗口中除了边框.标题栏.菜单栏以及状态栏外的中间部分)中进行绘图,坐标点(0,0)通常指的是客户区的左上角.它的 ...