小标
2018-05-23
来源 :
阅读 1283
评论 0
摘要:在Android应用开发中,实际开发中经常会遇到应用内截图的相关问题,如果是普通View的话我们可以使用View的绘图缓存来获取截图,但是RecyclerView和ScrollView呢就稍微有点不同了。希望对大家学习Android应用开发有所帮助。
思路
在Android应用开发中,实际开发中经常会遇到应用内截图的相关问题,如果是普通View的话我们可以使用View的绘图缓存来获取截图,但是RecyclerView和ScrollView呢就稍微有点不同了。希望对大家学习Android应用开发有所帮助。
ScrollView还好,只有一个子View,而RecyclerView中会有itemView重用的问题,只会绘制在屏幕上显示出来的itemView,因此我们可以依次获取每个itemView的视图存储到LruCache中,最后在进行拼装。这种方案有个问题就是如果数据过多可能会产生OOM问题,不过我测试的几百条item都还好,没有遇到。
代码
普通View
普通View截图就是获取View的绘图缓存,这里的代码很简单,先看看吧:
<code><code><code> //开启绘图缓存 view.setDrawingCacheEnabled(true); //这个方法可调可不调,因为在getDrawingCache()里会自动判断有没有缓存有没有准备好, //如果没有,会自动调用buildDrawingCache() view.buildDrawingCache(); //获取绘图缓存 这里直接创建了一个新的bitmap //因为我们在最后需要释放缓存资源,会释放掉缓存中创建的bitmap对象 Bitmap bitmap = Bitmap.createBitmap(view.getDrawingCache(), 0, 0, view.getMeasuredWidth(), view.getMeasuredHeight()); //清理绘图缓存,释放资源 view.destroyDrawingCache();</code></code></code>
可以看下destroyDrawingCache()方法的源码:
<code><code><code><code>public void destroyDrawingCache() {
if (mDrawingCache != null) {
mDrawingCache.recycle();
mDrawingCache = null;
}
if (mUnscaledDrawingCache != null) {
mUnscaledDrawingCache.recycle();
mUnscaledDrawingCache = null;
}
}</code></code></code></code>
如果你需要整个屏幕的截图,使用了DecorView来获取截图的话顶部会有状态栏的一条,可以通过获取状态栏高度,在重新创建Bitmap时截取掉。
RecyclerView截图
RecyclerView的截图稍微复杂些。我们可以先获取到rv的adapter对象,通过adapter对象手动调用创建和绑定ViewHolder等方法,模拟rv的加载过程,再依次保存每个itemView的绘图缓存,最后拼装成一个完整的Bitmap。看看代码吧~
1. 获取Adapter,通过Adapter获取每个itemView的绘图缓存
“` java
//获取设置的adapter
RecyclerView.Adapter adapter = view.getAdapter();
if (adapter == null) {
return null;
}
//创建保存截图的bitmap
Bitmap bigBitmap = null;
//获取item的数量
int size = adapter.getItemCount();
//recycler的完整高度 用于创建bitmap时使用
int height = 0;
//获取最大可用内存
final int maxMemory = (int) (Runtime.getRuntime().maxMemory() / 1024);<code><code><code><code><code><code> // 使用1/8的缓存
final int cacheSize = maxMemory / 8;
//把每个item的绘图缓存存储在LruCache中
LruCache<string, bitmap=""> bitmapCache = new LruCache<>(cacheSize);
for (int i = 0; i < size; i++) {
//手动调用创建和绑定ViewHolder方法,
RecyclerView.ViewHolder holder = adapter.createViewHolder(view, adapter.getItemViewType(i));
adapter.onBindViewHolder(holder, i);
//测量
holder.itemView.measure(
View.MeasureSpec.makeMeasureSpec(view.getWidth(), View.MeasureSpec.EXACTLY),
View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED));
//布局
holder.itemView.layout(0, 0, holder.itemView.getMeasuredWidth(),
holder.itemView.getMeasuredHeight());
//开启绘图缓存
holder.itemView.setDrawingCacheEnabled(true);
holder.itemView.buildDrawingCache();
Bitmap drawingCache = holder.itemView.getDrawingCache();
if (drawingCache != null) {
bitmapCache.put(String.valueOf(i), drawingCache);
}
//获取itemView的实际高度并累加
height += holder.itemView.getMeasuredHeight();
}
</string,></code></code></code></code></code></code>
2. 创建保存截图的Bitmap 把保存的itemView绘图缓存画上去
java
//根据计算出的recyclerView高度创建bitmap
bigBitmap = Bitmap.createBitmap(view.getMeasuredWidth(), height, Bitmap.Config.RGB_565);
//创建一个canvas画板
Canvas canvas = new Canvas(bigBitmap);
//获取recyclerView的背景颜色
Drawable background = view.getBackground();
//画出recyclerView的背景色 这里只用了color一种 有需要也可以自己扩展
if (background instanceof ColorDrawable) {
ColorDrawable colorDrawable = (ColorDrawable) background;
int color = colorDrawable.getColor();
canvas.drawColor(color);
}
//当前bitmap的高度
int top = 0;
//画笔
Paint paint = new Paint();
for (int i = 0; i < size; i++) {
Bitmap bitmap = bitmapCache.get(String.valueOf(i));
canvas.drawBitmap(bitmap, 0f, top, paint);
top += bitmap.getHeight();
}“
ScrollView截图
ScrollView的截图也比较简单,获取到子View的高度就好,而ScrollView只允许又一个子View。
<code><code><code><code><code><code><code> int height = 0;
//理论上scrollView只会有一个子View啦
for (int i = 0; i < view.getChildCount(); i++) {
height += view.getChildAt(i).getHeight();
}
//创建保存缓存的bitmap
Bitmap bitmap = Bitmap.createBitmap(view.getWidth(), height, Bitmap.Config.RGB_565);
//可以简单的把Canvas理解为一个画板 而bitmap就是块画布
Canvas canvas = new Canvas(bitmap);
//获取ScrollView的背景颜色
Drawable background = view.getBackground();
//画出ScrollView的背景色 这里只用了color一种 有需要也可以自己扩展 也可以自己直接指定一种背景色
if (background instanceof ColorDrawable) {
ColorDrawable colorDrawable = (ColorDrawable) background;
int color = colorDrawable.getColor();
canvas.drawColor(color);
}
//把view的内容都画到指定的画板Canvas上
view.draw(canvas);
return bitmap;</code></code></code></code></code></code></code>
关于Bitmap的recycle()方法
很多人以为这个释放资源的方法是必须调用的。其实不然,在2.3之后可以完全交由GC管理。
本文由职坐标整理并发布,希望对同学们有所帮助。了解更多详情请关注职坐标移动开发Android频道!
喜欢 | 0
不喜欢 | 0
您输入的评论内容中包含违禁敏感词
我知道了

请输入正确的手机号码
请输入正确的验证码
您今天的短信下发次数太多了,明天再试试吧!
我们会在第一时间安排职业规划师联系您!
您也可以联系我们的职业规划师咨询:
版权所有 职坐标-一站式AI+学习就业服务平台 沪ICP备13042190号-4
上海海同信息科技有限公司 Copyright ©2015 www.zhizuobiao.com,All Rights Reserved.
沪公网安备 31011502005948号