Android View类中,有这样一组神奇的截图方法:
setDrawingCacheEnabled(boolean enabled)
buildDrawingCache()
getDrawingCache()
destroyDrawingCache()
四个方法配合使用,让你可以获取任意View的Bitmap缓存,达到截图等作用。先来看一下这四个方法都代表什么:
1.setDrawingCacheEnabled(boolean enabled):
/** *
Enables or disables the drawing cache. When the drawing cache is enabled, the next call * to {@link #getDrawingCache()} or {@link #buildDrawingCache()} will draw the view in a * bitmap. Calling {@link #draw(android.graphics.Canvas)} will not draw from the cache when * the cache is enabled. To benefit from the cache, you must request the drawing cache by * calling {@link #getDrawingCache()} and draw it on screen if the returned bitmap is not * null.
*/public void setDrawingCacheEnabled(boolean enabled) {
mCachingFailed = false; setFlags(enabled ? DRAWING_CACHE_ENABLED : 0, DRAWING_CACHE_ENABLED);
}
直译理解,就是一个控制方法,enable设为true则可以使用buildDrawingCache()与getDrawingCache(),反之则无法使用。默认为true。
2.buildDrawingCache()&&buildDrawingCache(boolean autoScale):
/**
*Forces the drawing cache to be built if the drawing cache is invalid.
**If you call {@link #buildDrawingCache()} manually without calling * {@link #setDrawingCacheEnabled(boolean) *setDrawingCacheEnabled(true)}, you * should cleanup the cache by calling {@link #destroyDrawingCache()} afterwards.
**Note about auto scaling in compatibility mode: When auto scaling is not enabled, * this method will create a bitmap of the same size as *this view. Because this bitmap * will be drawn scaled by the parent ViewGroup, the result on screen might show * scaling artifacts. To *avoid such artifacts, you should call this method by setting * the auto scaling to true. Doing so, however, will generate a bitmap of a *different * size than the view. This implies that your application must be able to handle this * size.
**You should avoid calling this method when hardware acceleration is enabled. If * you do not need the drawing cache bitmap, calling this *method will increase memory * usage and cause the view to be rendered in software once, thus negatively impacting * performance.
*/
public void buildDrawingCache(boolean autoScale) {
...//此处省略杂七杂八的一堆代码
}
巴拉巴拉一堆注释,总之就是只要调用了这个方法,View就会生成一张自身的Bitmap图片。那么这个方法如何生成的,往下看真正的实现方法:
/**
*这才是真正的实现方法
*/
private void buildDrawingCacheImpl(boolean autoScale) {
...
int width = mRight - mLeft;
int height = mBottom - mTop;
...
try {
//重点:新建了一个跟View宽高一样的Bitmap
bitmap = Bitmap.createBitmap(mResources.getDisplayMetrics(), width, height, quality); bitmap.setDensity(getResources().getDisplayMetrics().densityDpi);
if (autoScale) {
mDrawingCache = bitmap;
} else {
mUnscaledDrawingCache = bitmap;
}
if (opaque && use32BitCache) bitmap.setHasAlpha(false);
} catch (OutOfMemoryError e) {
// If there is not enough memory to create the bitmap cache, just
// ignore the issue as bitmap caches are not required to draw the
// view hierarchy
if (autoScale) {
mDrawingCache = null;
} else {
mUnscaledDrawingCache = null;
}
mCachingFailed = true;
return;
}
...
Canvas canvas;
...
//重点:设置bitmap到 canvas中,准备绘制
canvas = new Canvas(bitmap);
...
//绘制
dispatchDraw(canvas);
}
上面代码省略了很多,这里只展示部分关键代码。总结一下,在buildDrawingCache()中,主要做了两件事情:
1)创建了一个空的bitmap(宽高跟autoScale有关,如果autoScale为false,宽高则为View的宽高)
2)使用Canvas将视图绘制到bitmap上
3.getDrawingCache()
4.destroyDrawingCache()
这两个方法没啥可说的了,顾名思义就不贴源码了。getDrawingCache()在没有检测到生成过bitmap的时候,会先调用一次buildDrawingCache()生成一张bitmap,如果检测到有的话,则返回之前生成的。
destroyDrawingCache()则是用来销毁之前生成的bitmap,释放资源。如果需要反复获取View的Bitmap视图,则需要配合destroyDrawingCache()方法,不然容易反复获取同一张bitmap。