App开发功能之一 – 截图:
代码如下:
view.destroyDrawingCache();
view.setDrawingCacheEnabled(true);
view.buildDrawingCache();
Bitmap map = view.getDrawingCache();
但是在部分机型上总是会有 map 为 null 的情况发生。
日志分析:
View: LinearLayout not displayed because it is too large to fit into a software layer (or drawing cache), needs 15223680 bytes, only 8294400 available
貌似是触发了系统的某些限制,说是控件太大了。当然也确实是比较长的一个控件。
源码分析:
view.buildDrawingCache() ->
buildDrawingCache(false) ->
buildDrawingCacheImpl(autoScale)
在 buildDrawingCacheImpl 中:
if (width <= 0 || height <= 0 || projectedBitmapSize > drawingCacheSize) {
if (width > 0 && height > 0) {
Log.w(VIEW_LOG_TAG, getClass().getSimpleName() + " not displayed because it is"
+ " too large to fit into a software layer (or drawing cache), needs "
+ projectedBitmapSize + " bytes, only "
+ drawingCacheSize + " available");
}
destroyDrawingCache();
mCachingFailed = true;
return;
}
width / height 在View正常显示的情况下都不为0,那么就是 projectedBitmapSize > drawingCacheSize 这个条件件被触发了:
final long projectedBitmapSize =
width * height * (opaque && !use32BitCache ? 2 : 4);
final long drawingCacheSize =
ViewConfiguration.get(mContext).getScaledMaximumDrawingCacheSize();
ViewConfiguration.get(mContext).getScaledMaximumDrawingCacheSize() 得到的是系统所提供的最大的DrawingCache的值。
从上面的分析中可以看到View过大,超出了系统DrawingCache的限制导致了view.buildDrawingCache() 方法没有生效,最终 Bitmap map = view.getDrawingCache() 中map为null。
解决方案:
public static BitmapWithHeight getSimpleViewToBitmap(final View view, int width) throws OutOfMemoryError {
if (view.getWidth() <= 0 || view.getHeight() <= 0) {
view.measure(View.MeasureSpec.makeMeasureSpec(width, View.MeasureSpec.EXACTLY),
View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED));
view.layout(0, 0, view.getMeasuredWidth(), view.getMeasuredHeight());
}
view.destroyDrawingCache();
view.setDrawingCacheEnabled(true);
view.buildDrawingCache();
Bitmap map = view.getDrawingCache();
if (view.getHeight() > 0 && map == null)
map = getViewBitmap(view);
return new BitmapWithHeight(map, view.getMeasuredWidth(), view.getMeasuredHeight());
}
public static Bitmap getViewBitmap(View view) {
Bitmap bitmap;
if (view.getWidth() > 0 && view.getHeight() > 0)
bitmap = Bitmap.createBitmap(view.getWidth(), view.getHeight(), Bitmap.Config.ARGB_8888);
else if (view.getMeasuredWidth() > 0 && view.getMeasuredHeight() > 0)
bitmap = Bitmap.createBitmap(view.getMeasuredWidth(), view.getMeasuredHeight(), Bitmap.Config.ARGB_8888);
else
bitmap = Bitmap.createBitmap(com.blankj.utilcode.utils.ScreenUtils.getScreenWidth(), com.blankj.utilcode.utils.ScreenUtils.getScreenHeight() * 2, Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(bitmap);
view.draw(canvas);
return bitmap;
}