🔥码云GVP开源项目 12k star Uniapp+ElementUI 功能强大 支持多语言、二开方便! 广告
[TOC] # 1. 前言 本篇文章中将简单讲解下什么事离屏绘制。在Android中简要来说也就是将要绘制的内容单独绘制在缓冲层,而在Android中提供了canvas.saveLayer方法来保存当前图层作为离屏缓冲,在绘制完毕后可以使用canvas.restoreToCount(saveId)或者canvas.restore();来恢复之前的图层。这是什么意思呢?不妨来做一个简单的小实验: 比如,我这里的需求为绘制两个圆,并且让两个圆分开间隔20dp,水平对齐。当然,这里不直接产生两个已经满足条件的圆,而是使用这里的离屏绘制,也就是新增一个图层。假定两个圆的位置如下: ![](https://img.kancloud.cn/c5/ed/c5edb44a6db8108292e6b7b260704541_518x334.png) 对应代码: ~~~ private lateinit var mOtherPaint: Paint private lateinit var mPaint: Paint // 圆中心和半径 private var mCx = 300 private var mCy = 300 private var mRadius = 100 private fun init(){ mPaint = Paint() mPaint.isAntiAlias = true mPaint.color = Color.RED mPaint.isDither = true mPaint.strokeWidth = 5f mPaint.style = Paint.Style.FILL mOtherPaint = Paint() mOtherPaint.isAntiAlias = true mOtherPaint.color = Color.BLUE mOtherPaint.isDither = true mOtherPaint.strokeWidth = 5f mOtherPaint.style = Paint.Style.FILL } override fun onDraw(canvas: Canvas?) { super.onDraw(canvas) canvas?.apply { // 只有一个图层情况 drawCircle(mCx.toFloat(), mCy.toFloat(), mRadius.toFloat(), mPaint) drawCircle(mCx.toFloat() + 50, mCy.toFloat() + 50, mRadius.toFloat(), mOtherPaint) } } ~~~ 如果只有一个图层,那么我们就需要修改两个圆的坐标位置。这里我们使用新建一个图层的方式。也就是: ~~~ override fun onDraw(canvas: Canvas?) { super.onDraw(canvas) canvas?.apply { // 只有一个图层情况 drawCircle(mCx.toFloat(), mCy.toFloat(), mRadius.toFloat(), mPaint) // 存储当前图层 val saveLayerId = saveLayer(0f, 0f, width.toFloat(), height.toFloat(), mPaint) // 移动画布 translate((20 + mRadius * 2).toFloat(), 0f) drawCircle(mCx.toFloat(), mCy.toFloat(), mRadius.toFloat(), mOtherPaint) // 恢复之前图层 restoreToCount(saveLayerId) } } ~~~ 结果: ![](https://img.kancloud.cn/6e/ce/6ece7eab38a0b5b57790afce682e81ad_209x106.png) 从结果中可以看出,其实这里可以理解为创建了一个新的图层,然后可以对新图层进行简单平移操作,然后绘制对应的图层内容,继而最终在上一个图层恢复的时候可以将多个(两个)图层合并。 # 2. 其他 View.setLayerType()直接把整个View都绘制在离屏缓冲中 ```java //使用一个Bitmap来缓冲,通常也就是设置禁用硬件加速 setLayerType(LAYER_TYPE_SOFTWARE, null); //使用GPU来缓冲 setLayerType(LAYER_TYPE_HARDWARE, null); ```