业务中遇到了需要局部截图的业务逻辑,百度出来使用缓存的方式截图,但是copy后发现好多删除线,然后官方文档提示已经过时,建议使用PIxelCopy API
For screenshots of the UI for feedback reports or unit testing the PixelCopy API is recommended.
现将我封装的代码复制出来,大家直接用吧!
/**
* 将View转换成Bitmap
*/
fun createBitmapFromView(window: Window, view: View, callBack: (Bitmap?, Boolean) -> Unit) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
var bitmap = Bitmap.createBitmap(view.width, view.height, Bitmap.Config.ARGB_8888, true)
convertLayoutToBitmap(
window, view, bitmap
) { copyResult -> //如果成功
if (copyResult == PixelCopy.SUCCESS) {
callBack(bitmap,true)
}else{
callBack(null,false)
}
}
} else {
var bitmap: Bitmap? = null
//开启view缓存bitmap
view.isDrawingCacheEnabled = true
//设置view缓存Bitmap质量
view.drawingCacheQuality = View.DRAWING_CACHE_QUALITY_HIGH
//获取缓存的bitmap
val cache: Bitmap = view.getDrawingCache()
if (cache != null && !cache.isRecycled) {
bitmap = Bitmap.createBitmap(cache)
}
//销毁view缓存bitmap
view.destroyDrawingCache()
//关闭view缓存bitmap
view.setDrawingCacheEnabled(false)
callBack(bitmap,bitmap!=null)
}
}
@RequiresApi(Build.VERSION_CODES.O)
private fun convertLayoutToBitmap(
window: Window, view: View, dest: Bitmap,
listener: PixelCopy.OnPixelCopyFinishedListener
) {
//获取layout的位置
val location = IntArray(2)
view.getLocationInWindow(location)
//请求转换
PixelCopy.request(
window,
Rect(location[0], location[1], location[0] + view.width, location[1] + view.height),
dest, listener, Handler(Looper.getMainLooper())
)
}
保存图片一起复制出来吧!
fun saveBitmapGallery(context: Context, bitmap: Bitmap): Boolean {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
//返回出一个URI
val insert = context.contentResolver.insert(
MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
/*
这里如果不写的话 默认是保存在 /sdCard/DCIM/Pictures
*/
ContentValues()//这里可以啥也不设置 保存图片默认就好了
) ?: return false //为空的话 直接失败返回了
//这个打开了输出流 直接保存图片就好了
context.contentResolver.openOutputStream(insert).use {
it ?: return false
bitmap.compress(Bitmap.CompressFormat.JPEG, 100, it)
}
return true
} else {
MediaStore.Images.Media.insertImage(context.contentResolver, bitmap, "title", "desc")
return true
}
}
fun saveFile2Gallery(context: Context, url: String): Boolean {
//返回出一个URI
val insert = context.contentResolver.insert(
MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
/*
这里可以默认不写 默认保存在
*/
ContentValues()
) ?: return false //为空的话 直接失败返回了
//这个打开了输出流 直接保存图片就好了
context.contentResolver.openOutputStream(insert).use { os ->
os ?: return false
var x = download(url, os)
return x
}
return false
}
private fun download(url: String, os: OutputStream): Boolean {
val url = URL(url)
(url.openConnection() as HttpURLConnection).also { conn ->
conn.requestMethod = "GET"
conn.connectTimeout = 5 * 1000
if (conn.responseCode == 200) {
conn.inputStream.use { ins ->
val buf = ByteArray(2048)
var len: Int
while (ins.read(buf).also { len = it } != -1) {
os.write(buf, 0, len)
}
os.flush()
}
return true
} else {
return false
}
}
}
使用
下面用到了kotlin1.4的特性 SAM转换,不知道低版本支不支持,应该可以用普通的lambda传参
PhotoUtils.createBitmapFromView(window, binding.cvShare) {bitmap,isCopySuccess->
if(isCopySuccess){
bitmap?.let {
PhotoUtils.saveBitmapGallery(this, bitmap)
showPromptMessage("保存成功")
}
}else{
showPromptMessage("保存失败")
}
}