How to get a drawable that mirror version of another drawable?

Background

I know that it is possible to create a rotating version of Drawable (or Bitmap) as such (written about it here ):

@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()
        }
    }
}

Problem

I wanted it to autoMirroredbe installed on some drawable (VectorDrawable in my case) that would flip over (mirror so that the left one is right and the right one is left, but does not affect the top and bottom) if the locale of the device is RTL.

As an example (and this is just an example!), If you take a drawable that shows a left arrow, after clicking it will be a right arrow.

Unfortunately, this is only available from API 19.

That's why I decided to make it a new Drawable, to be an upside down version of the original

What i tried

, , . :

    @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()
            }
        }
    }

, - . , , , .

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)
        }
    }
}
+4
3

.

matrix.preScale(-1.0f, 1.0f, canvas.getWidth() / 2, canvas.getHeight() / 2);

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; }
}

:

    Drawable drawable = getResources().getDrawable(R.drawable.your_drawable);
    getSupportActionBar().setHomeAsUpIndicator(new MirroredDrawable(drawable));
+2

android:scaleX="-1" xml, . , :

<ImageView
    android:scaleX="@integer/rtl_flip_factor"
    android:src="@android:drawable/ic_media_play"/>

, values/integers.xml (LTR)

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <integer name="rtl_flip_factor">1</integer>
</resources>

values-ldrtl/integers.xml RTL:

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <integer name="rtl_flip_factor">-1</integer>
</resources>
0

You can use the Group tag to achieve the same.

Here is an example:

<vector xmlns:android="http://schemas.android.com/apk/res/android"
    android:width="24dp"
    android:height="24dp"
    android:viewportHeight="24.0"
    android:viewportWidth="24.0">
    <group
        android:name="rotationGroup"
        android:rotation="@dimen/rotation_degree">
        <path .... />
    </group>
</vector>

Now define the different sizes of rot_degree in the normal values ​​folder and the ldrtl folder.

In the values ​​folder as

<item name="rotation_degree" format="float" type="dimen">0.0</item>

In values-ldrtl like

<item name="rotation_degree" format="float" type="dimen">180.0</item>
0
source

Source: https://habr.com/ru/post/1692265/


All Articles