如何创建指定Drawable的镜像版本?适配Android低API版本
实现Drawable的水平镜像翻转(适配API 19以下)
我明白你的需求:要给VectorDrawable实现类似autoMirrored的效果,在RTL语言环境下完成水平翻转(左右互换、不影响上下),但这个系统属性仅在API 19及以上可用,所以需要手动实现镜像版本,还要贴合你之前旋转Drawable的实现思路。
为什么你之前的尝试会失效?
你之前用Matrix做水平缩放的代码,问题出在只做了画布翻转,却没调整Drawable的绘制边界——翻转后Drawable的绘制位置直接超出了承载View的可视区域,所以看起来像是完全不显示了。
可行的实现方案
结合你之前旋转Drawable的思路,我们可以通过LayerDrawable包装原Drawable,在绘制时同步调整画布矩阵和Drawable的绘制边界,确保它能正确显示在View内部:
fun Drawable.getMirroredDrawable(): Drawable { return object : LayerDrawable(arrayOf(this)) { val drawingRect = Rect() val matrix = Matrix() override fun draw(canvas: Canvas) { matrix.reset() // 以画布中心为原点完成水平翻转 matrix.preScale(-1.0f, 1.0f, canvas.width / 2.0f, canvas.height / 2.0f) canvas.matrix = matrix // 计算Drawable在画布中的居中绘制区域 drawingRect.left = (canvas.width - intrinsicWidth) / 2 drawingRect.top = (canvas.height - intrinsicHeight) / 2 drawingRect.right = drawingRect.left + intrinsicWidth drawingRect.bottom = drawingRect.top + intrinsicHeight // 更新Drawable的bounds到计算好的区域,避免绘制偏移 if (bounds != drawingRect) bounds = drawingRect super.draw(canvas) } } }
关键细节解释
- Matrix翻转逻辑:
matrix.preScale(-1.0f, 1.0f, canvas.width / 2.0f, canvas.height / 2.0f)是核心,它以画布中心为基准点进行水平翻转,避免Drawable整体偏移出画布范围。 - 调整Drawable Bounds:通过计算居中的
drawingRect,把Drawable的绘制边界锁定在这个区域,确保翻转后的内容能完整显示在View的可视范围内。 - 复用LayerDrawable:和你之前旋转Drawable的实现方式一致,用
LayerDrawable包装原Drawable,不需要额外创建Bitmap,既能保留VectorDrawable的矢量特性,也能保证性能。
使用方式
直接在需要镜像的Drawable上调用这个扩展函数即可:
val originalDrawable = ContextCompat.getDrawable(context, R.drawable.ic_left_arrow) val mirroredDrawable = originalDrawable?.getMirroredDrawable()
内容的提问来源于stack exchange,提问作者android developer
相关产品推荐
相关产品推荐

