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 ...
随机推荐
- kentico检查当前授权用户,是否为admin角色
https://docs.kentico.com/k11/custom-development/user-internals-and-api/checking-permissions-using-th ...
- 内部类 final变量的生命周期
(1).内部类是外部类的一个成员,就像外部类的成员方法一样,所以内部类有权限访问外部类的所有成员,包括private的. (2).内部类不能访问外部类方法中的局部变量,除非变量是final的(一般发生 ...
- BZOJ1040:骑士(基环树DP)
Z国的骑士团是一个很有势力的组织,帮会中汇聚了来自各地的精英.他们劫富济贫,惩恶扬善,受到社会各界的赞扬.最近发生了一件可怕的事情,邪恶的Y国发动了一场针对Z国的侵略战争.战火绵延五百里,在和平环境中 ...
- E20170512-hm
implicit adj. 不言明[含蓄]的; 无疑问的, conversion n. 变换,转变; precision n. 精确度, adj. 精确的, with precision 准确地 ...
- 第九篇 .NET高级技术ref、out
普通参数是“值类型传递拷贝,引用类型传递引用”,但是都不能在函数内部修改外部变量的指向(p.Age=5不是可以吗?),这时候要用ref或者out(相当于把变量都传进去了),他们的作用不同:ref的作用 ...
- iOS音频与视频的开发(二)- 使用AVAudioRecorder进行录制音频
1.使用AVAudioRecorder录制视频 AVAudioRecorder与AVAudioPlayer类似,它们都属于AVFoundation的类.AVAudioRecorder的功能类似于一个录 ...
- locale localedef --之Linux字符集理解
参考: https://www.cnblogs.com/dolphi/p/3622420.html http://www.360doc.com/content/15/1105/08/14513 ...
- Spring事务引发dubbo服务注册问题
文章清单 1. 问题 2. 查找bug过程 3. 解决方案 使用spring boot+dubbo写项目,一个服务,之前是正常的,后来调用方出现空指针异常,第一反应提供方出了问题. 1. 看控制台,服 ...
- python实现堆排序
理论知识: 二叉树:度不超过2的树(节点最多有两个叉) 满二叉树:一个二叉树,如果每一个层的节点数都达到最大值,则这个二叉树就是满二叉树. 完全二叉树:叶节点只能出现在最下层和次下层,并且最下面一层的 ...
- 莫比乌斯函数 && HDU-1695
莫比乌斯函数定义: $$\mu(d)=\begin{cases}1 &\text{d = 1}\\(-1)^r &\text{$d=p_1p_2...p_r,其中p_i为不同的素数$} ...