最近在看Android的系统源码,在看到View的源码的时候,无意间看到了在源码中有这么一个函数:
/**
* Create a snapshot of the view into a bitmap. We should probably make
* some form of this public, but should think about the API.
*/
Bitmap createSnapshot(Bitmap.Config quality, int backgroundColor, boolean skipChildren) {
通过注释,我可以知道,这个函数就是用于将View绘制的内容保存到一个Bitmap中进行返回,用户需要的话可以将该
Bitmap保存到任意位置。看到这里,我突然想起来,以前用过网上的保存View到图片的代码,这里先贴上两份代码:
1.网络上的保存代码:
Bitmap bitmap = Bitmap.createBitmap(ivTest.getMeasuredWidth(), ivTest.getMeasuredHeight(), Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas();
canvas.setBitmap(bitmap);
ivTest.draw(canvas);
2.View中的createSnapshot中的代码:
代码稍微有点长,但是考虑的方面比较多。所以,效果也比较好,后面会有对比:
/**
* Create a snapshot of the view into a bitmap. We should probably make
* some form of this public, but should think about the API.
*/
Bitmap createSnapshot(Bitmap.Config quality, int backgroundColor, boolean skipChildren) {
int width = mRight - mLeft;
int height = mBottom - mTop;
final AttachInfo attachInfo = mAttachInfo;
final float scale = attachInfo != null ? attachInfo.mApplicationScale : 1.0f;
width = (int) ((width * scale) + 0.5f);
height = (int) ((height * scale) + 0.5f);
Bitmap bitmap = Bitmap.createBitmap(mResources.getDisplayMetrics(),
width > 0 ? width : 1, height > 0 ? height : 1, quality);
if (bitmap == null) {
throw new OutOfMemoryError();
}
Resources resources = getResources();
if (resources != null) {
bitmap.setDensity(resources.getDisplayMetrics().densityDpi);
}
Canvas canvas;
if (attachInfo != null) {
canvas = attachInfo.mCanvas;
if (canvas == null) {
canvas = new Canvas();
}
canvas.setBitmap(bitmap);
.........
attachInfo.mCanvas = null;
} else {
// This case should hopefully never or seldom happen
canvas = new Canvas(bitmap);
}
if ((backgroundColor & 0xff000000) != 0) { //用于处理背景
bitmap.eraseColor(backgroundColor);
}
.........
// Fast path for layouts with no backgrounds
if ((mPrivateFlags & PFLAG_SKIP_DRAW) == PFLAG_SKIP_DRAW) {
dispatchDraw(canvas);
if (mOverlay != null && !mOverlay.isEmpty()) {
mOverlay.getOverlayView().draw(canvas);
}
} else {
draw(canvas);
}
mPrivateFlags = flags;
canvas.restoreToCount(restoreCount);
canvas.setBitmap(null);
if (attachInfo != null) {
// Restore the cached Canvas for our siblings
attachInfo.mCanvas = canvas;
}
return bitmap;
}
通过对比,可以看出,两个代码的实现思路相似,createSnapshot中的代码对背景使用eraseColor进行了处理。
同时,看到这里,我发现,在注释中也没有API的限制,同时,官方也有意将改API暴漏出来,想着练练手的目的,我想着用反射看看能不能调用到这个函数呢?答案肯定是可以的,下面直接上我的代码:
private void saveViewUserInvoke(){
Class cls = ivTest.getClass();
while (!cls.getName().equals("android.view.View")){
cls = cls.getSuperclass();
}
try {
Method method = cls.getDeclaredMethod("createSnapshot", new Class[]{Bitmap.Config.class, int.class, boolean.class});
method.setAccessible(true);
Bitmap bitmap = (Bitmap) method.invoke(ivTest, Bitmap.Config.ARGB_8888, Color.WHITE, false);
saveBitmapToFile(bitmap); //自定义的保存函数
} catch (Exception e) {
e.printStackTrace();
}
}
这样就可以简单的,并且完美的保存图片到本地了。下面贴上效果图:右边是保存后的效果。