How can we tile a vector image?

Viewed 4006

With the support library now fully supporting vector images, I'm trying to switch to vector images as much as I can in my app. An issue I'm running into is that it seems impossible to repeat them.

With bitmap images the following xml could be used:

<bitmap
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:src="@drawable/repeat_me"
    android:tileMode="repeat"
    />

This does not work, as vector images can not be used in bitmaps: https://code.google.com/p/android/issues/detail?id=187566

Is there any other way to tile/repeat vector images?

5 Answers

This is the java version of Nick Butcher solution:

import android.graphics.Bitmap;
import android.graphics.BitmapShader;
import android.graphics.Canvas;
import android.graphics.ColorFilter;
import android.graphics.Paint;
import android.graphics.PixelFormat;
import android.graphics.Shader;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;

public class TileDrawable extends Drawable {

    private final Paint paint;

    public TileDrawable(Drawable drawable, Shader.TileMode tileMode) {
        paint = new Paint();
        paint.setShader(new BitmapShader(getBitmap(drawable), tileMode, tileMode));
    }

    @Override
    public void draw(@NonNull Canvas canvas) {
        canvas.drawPaint(paint);
    }

    @Override
    public void setAlpha(int alpha) {
        paint.setAlpha(alpha);
    }

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

    @Override
    public int getOpacity() {
        return PixelFormat.TRANSLUCENT;
    }

    private Bitmap getBitmap(Drawable drawable) {
        if (drawable instanceof BitmapDrawable)
            return ((BitmapDrawable) drawable).getBitmap();
        Bitmap bitmap = Bitmap.createBitmap(drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight(), Bitmap.Config.ARGB_8888);
        Canvas canvas = new Canvas(bitmap);
        drawable.setBounds(0, 0, drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight());
        drawable.draw(canvas);
        return bitmap;
    }

}

You can use this drawable class in code with vector patterns:

view.setBackground(new TileDrawable(getContext().getDrawable(R.drawable.pattern), Shader.TileMode.REPEAT));

I see 2 easy workarounds to this problem:

1. To create (repeat) pattern you want in SVG manipulative software like 'Inkscape' or 'CorelDraw'. And then use this 'created_manually_pattern_svg' in your 'ImageView' as

... 
app:srcCompat="@drawable/created_manually_pattern_svg"
...

or even

...
android:background="@drawable/created_manually_pattern_svg"
...

in any ather 'view' (but i'm not sure if it works in all API levels)

2. Export your '.svg' file into '.png' and then use 'bitmap'.

Related