0

I'm trying to visualize a rotating object on an Android 9 device by programmatically rotating a vector drawable, created from a .svg file using the New->Vector Asset method. The rotation of the object should follow the changes of some external property, instead of a predefined animation.

When a vector image is drawn on an ImageView as a VectorDrawable, the image produced has smooth edges as it should, but when the image is rotated programmatically using a RotateDrawable, the edges become jagged, as if the image was treated as a bitmap, and not redrawn as vector graphics.

The image below illustrates this problem:

Below is the pure Drawable, top is the rotated version with jagged edges

According to the VectorDrawable documentation, a bitmap cache is created for each vector asset when it is first loaded, but is there a possibility to force the re-rendering when the image is rotated?

Below is some sample code used to create the effect.

Drawable class:

    public class MyDrawable extends Drawable implements Drawable.Callback, Runnable {

    @Override
    public void draw(Canvas canvas)
    {
        VectorDrawable vectorDrawable = (VectorDrawable)mainActivity.getResources().getDrawable(R.drawable.test_drawable, mainActivity.getTheme());
        vectorDrawable.setBounds(canvas.getClipBounds());
        vectorDrawable.draw(canvas);    // This looks OK

        RotateDrawable rotator = new RotateDrawable();
        rotator.setBounds(canvas.getClipBounds());
        rotator.setLevel(1000);
        rotator.setDrawable(vectorDrawable.mutate());
        rotator.draw(canvas);       // Jagged edges
    }
}

Used in an ImageView in a Fragment:

    @Override
    public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
        final ImageView testView = (ImageView)getView().findViewById(R.id.test_view);
        testView.setImageDrawable(new MyDrawable());
    }
Mibez
  • 21
  • 3
  • `"as if the image was treated as a bitmap"` this is exactly how `VectorDrawable` renders itself - only `AnimatedVectorDrawable` draws itself without that additional bitmap – pskink Sep 19 '19 at 10:13
  • What I'm trying to achieve is to dynamically change the rotation of a `VectorDrawable` based on the changing value of some external property. As far as I've understood `AnimatedVectorDrawable` can only be used to carry out predefined animations, which is not what I'm looking for. – Mibez Sep 19 '19 at 10:26
  • use `kyrie` then - it is @github – pskink Sep 19 '19 at 10:27
  • why dont you simple xml animation like this : https://stackoverflow.com/a/4846255/8528047 and if you are going for complex animations u can use lottie and make them in after effects. – Pemba Tamang Sep 19 '19 at 10:44
  • Use an SVG rendering library instead. This usage is not what VectorDrawables are intended for. – Paul LeBeau Sep 19 '19 at 13:21

1 Answers1

0

There seems to be no built-in support currently in Android for what I'm trying to achieve, but I found at least one working solution, which is to use the third-party AndroidSVG library and modify the .svg upper-most group <g> element directly to include a transformation:

@Override
public void draw(Canvas canvas)
{
    try {

        String svgString = // Your .svg file as plaintext
        svgString = svgString.replaceFirst("<g>", "<g transform=\"rotate(" + angle + ", " + pivotX + " , " + pivotY + ")\">");
        SVG svg = SVG.getFromString(svgString);
        svg.renderToCanvas(canvas);

        // ...
    }
    catch (SVGParseException svgpe){}

}
Mibez
  • 21
  • 3