Android Canvas画布saveLayer与对应restoreToCount,Kotlin
Kotlin
private fun mydraw() {
val originBmp = BitmapFactory.decodeResource(resources, R.mipmap.pic).copy(Bitmap.Config.ARGB_8888, true)
val newBmp = Bitmap.createBitmap(originBmp.width, originBmp.height, Bitmap.Config.ARGB_8888)
val canvas = Canvas(newBmp)
//把原图绘制在画布Canvas
canvas.drawBitmap(originBmp, 0f, 0f, null)
iv?.setImageURI(Uri.fromFile(saveBitmapToFile(newBmp)))
val paint = Paint(Paint.ANTI_ALIAS_FLAG)
paint.color = Color.RED
paint.textSize = 40f
paint.style = Paint.Style.STROKE
paint.strokeWidth = 2f
paint.textAlign = Paint.Align.LEFT
//新图层,绿色背景,红色圆圈。
val layer1 = canvas.saveLayer(0f, 0f, canvas.width.toFloat(), (canvas.height.toFloat() * 0.9).toFloat(), null)
canvas.drawColor(Color.GREEN)
canvas.drawCircle((canvas.width / 2).toFloat(), (canvas.height / 2).toFloat(), 50f, paint)
canvas.restoreToCount(layer1)
iv1?.setImageURI(Uri.fromFile(saveBitmapToFile(newBmp)))
//新图层,灰色背景,直线。
val layer2 = canvas.saveLayer(0f, 0f, canvas.width.toFloat(), (canvas.height.toFloat() * 0.8).toFloat(), null)
canvas.drawColor(Color.GRAY)
canvas.drawLine(
canvas.width.toFloat() / 2,
canvas.height.toFloat() / 2,
canvas.width.toFloat(),
canvas.height.toFloat(),
paint
)
canvas.restoreToCount(layer2)
iv2?.setImageURI(Uri.fromFile(saveBitmapToFile(newBmp)))
//新图层,绿色背景,文字fly
val layer3 = canvas.saveLayer(0f, 0f, canvas.width.toFloat(), (canvas.height.toFloat() * 0.5).toFloat(), null)
canvas.drawColor(Color.BLUE)
val x = 50f
val y = 150f
canvas.drawText("fly", x, y, paint)
canvas.restoreToCount(layer3)
iv3?.setImageURI(Uri.fromFile(saveBitmapToFile(newBmp)))
/**
* 如果不事先把bitmap通过文件形式存放好,再通过setImageURI设置到ImageView,那么就像
* iv4?.setImageBitmap(newBmp),设置的newBmp是最终的绘图结果,saveLayer与restoreToCount操作的是在内存的newBmp,
* 即便是ivx?.setImageURI后,newBmp内存数据变化,最终都是iv4里面的显示。为了细致观察这种区别,才先保存成不变的文件,再读文件加载出来观察。
*
* 注意,因为restoreToCount了,图层叠加到原图上,所以显示的结果是最后面的叠加到最前面的,把最前面的遮住了。
* 如果不restoreToCount,则不会叠加,因为saveLayer创建了一个透明图层,是在原图之上的绘制。
*/
iv4?.setImageBitmap(newBmp)
}
private fun saveBitmapToFile(bm: Bitmap): File? {
var saveFile: File? = null
val savePath =
Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES).toString()
if (!Files.exists(Paths.get(savePath))) {
Log.d("保存文件", "${savePath}不存在!")
} else {
saveFile = File(savePath, System.currentTimeMillis().toString() + ".jpeg")
try {
val saveImgOut = FileOutputStream(saveFile)
//压缩
bm.compress(Bitmap.CompressFormat.JPEG, 90, saveImgOut)
saveImgOut.flush()
saveImgOut.close()
Log.d("保存文件", "Bitmap保存至 ${saveFile.absoluteFile.toPath()}")
} catch (e: Exception) {
e.printStackTrace()
}
}
return saveFile
}
如果把
Kotlin
canvas.restoreToCount()
全部注释掉,则为