如何获得Drawable,它是不同Drawable的镜像版本?

and*_*per 6 android image-rotation android-drawable

背景

我知道可以创建一个Drawable(或Bitmap)的旋转版本,因此(在这里写一下):

@JvmStatic
fun getRotateDrawable(d: Drawable, angle: Int): Drawable {
    if (angle % 360 == 0)
       return d
    return object : LayerDrawable(arrayOf(d)) {
        override fun draw(canvas: Canvas) {
            canvas.save()
            canvas.rotate(angle.toFloat(), (d.bounds.width() / 2).toFloat(), (d.bounds.height() / 2).toFloat())
            super.draw(canvas)
            canvas.restore()
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

问题

我想要autoMirrored设置为一些drawable(在我的情况下是VectorDrawable),它将翻转(镜像使得左边是右边,右边是左边,但不影响顶部和底部),以防设备的区域设置是RTL.

作为一个例子(这只是一个例子!),如果你拿一个显示左箭头的drawable,翻转后它将是一个右箭头.

遗憾的是,这只能从API 19获得.

这就是为什么我决定用它制作一个新的Drawable,成为原版的翻版

我试过的

我发现了一篇很好的文章,在这里使用Matrix 对View做同样的事情.所以我试过这个:

    @JvmStatic
    fun getMirroredDrawable(d: Drawable): Drawable {
        return object : LayerDrawable(arrayOf(d)) {
            override fun draw(canvas: Canvas) {
                canvas.save()
                val matrix = Matrix()
                // use this for the other flipping: matrix.preScale(1.0f, -1.0f)
                matrix.preScale(-1.0f, 1.0f);
                canvas.matrix = matrix
                super.draw(canvas)
                canvas.restore()
            }
        }
    }
Run Code Online (Sandbox Code Playgroud)

可悲的是,出于某种原因,这使得抽签根本没有显示出来.也许它确实有效,但试图从它显示它的任何View的界限中展示出来.

这个问题

如何制作给定Drawable的翻转版本,类似于我为旋转Drawable所做的操作?


解:

基于下面建议的答案(这里),这是一个很好的方法:

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
            drawingRect.left = (canvas.width - intrinsicWidth) / 2
            drawingRect.top = (canvas.height - intrinsicHeight) / 2
            drawingRect.right = drawingRect.left + intrinsicWidth
            drawingRect.bottom = drawingRect.top + intrinsicHeight
            if (bounds != drawingRect)
                bounds = drawingRect
            super.draw(canvas)
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

Che*_*amp 5

指定翻转操作的中心。

matrix.preScale(-1.0f, 1.0f, canvas.getWidth() / 2, canvas.getHeight() / 2);
Run Code Online (Sandbox Code Playgroud)

这是一个Drawable可用于镜像可绘制对象的自定义类:

public class MirroredDrawable extends Drawable {
    final Drawable mDrawable;
    final Matrix matrix = new Matrix();

    MirroredDrawable(Drawable drawable) {
        mDrawable = drawable;
    }

    @Override
    public void draw(@NonNull Canvas canvas) {
        matrix.reset();
        matrix.preScale(-1.0f, 1.0f, canvas.getWidth() / 2, canvas.getHeight() / 2);
        canvas.setMatrix(matrix);

        Rect drawingRect = new Rect();
        drawingRect.left = (canvas.getWidth() - mDrawable.getIntrinsicWidth()) / 2;
        drawingRect.top = (canvas.getHeight() - mDrawable.getIntrinsicHeight()) / 2;
        drawingRect.right = drawingRect.left + mDrawable.getIntrinsicWidth();
        drawingRect.bottom = drawingRect.top + mDrawable.getIntrinsicHeight();
        mDrawable.setBounds(drawingRect);
        mDrawable.draw(canvas);
    }

    // Other methods required to extend Drawable but aren't used here.

    @Override
    public void setAlpha(int alpha) { }

    @Override
    public void setColorFilter(@Nullable ColorFilter colorFilter) { }

    @Override
    public int getOpacity() { return PixelFormat.OPAQUE; }
}
Run Code Online (Sandbox Code Playgroud)

以下是它的应用方法:

    Drawable drawable = getResources().getDrawable(R.drawable.your_drawable);
    getSupportActionBar().setHomeAsUpIndicator(new MirroredDrawable(drawable));
Run Code Online (Sandbox Code Playgroud)