我们如何平铺矢量图像?

DrB*_*lot 15 android vector-graphics

现在支持库完全支持矢量图像,我正试图在我的应用程序中尽可能多地切换到矢量图像.我遇到的一个问题是,似乎无法重复它们.

使用位图图像,可以使用以下xml:

<bitmap
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:src="@drawable/repeat_me"
    android:tileMode="repeat"
    />
Run Code Online (Sandbox Code Playgroud)

这不起作用,因为矢量图像无法用于位图:https://code.google.com/p/android/issues/detail? id = 187566

是否还有其他方法来平铺/重复矢量图像?

Hex*_*ise 7

这是 Nick Butcher 解决方案的 Java 版本:

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

}
Run Code Online (Sandbox Code Playgroud)

您可以在带有矢量模式的代码中使用这个 drawable 类:

view.setBackground(new TileDrawable(getContext().getDrawable(R.drawable.pattern), Shader.TileMode.REPEAT));
Run Code Online (Sandbox Code Playgroud)


DrB*_*lot 6

感谢@pskink我做了一个drawable,瓦片另一个drawable:https://gist.github.com/9ffbdf01478e36194f8f

这必须在代码中设置,不能从XML中使用:

public class TilingDrawable extends android.support.v7.graphics.drawable.DrawableWrapper {

    private boolean callbackEnabled = true;

    public TilingDrawable(Drawable drawable) {
        super(drawable);
    }

    @Override
    public void draw(Canvas canvas) {
        callbackEnabled = false;
        Rect bounds = getBounds();
        Drawable wrappedDrawable = getWrappedDrawable();

        int width = wrappedDrawable.getIntrinsicWidth();
        int height = wrappedDrawable.getIntrinsicHeight();
        for (int x = bounds.left; x < bounds.right + width - 1; x+= width) {
            for (int y = bounds.top; y < bounds.bottom + height - 1; y += height) {
                wrappedDrawable.setBounds(x, y, x + width, y + height);
                wrappedDrawable.draw(canvas);
            }
        }
        callbackEnabled = true;
    }

    @Override
    protected void onBoundsChange(Rect bounds) {
    }

    /**
     * {@inheritDoc}
     */
    public void invalidateDrawable(Drawable who) {
        if (callbackEnabled) {
            super.invalidateDrawable(who);
        }
    }

    /**
     * {@inheritDoc}
     */
    public void scheduleDrawable(Drawable who, Runnable what, long when) {
        if (callbackEnabled) {
            super.scheduleDrawable(who, what, when);
        }
    }

    /**
     * {@inheritDoc}
     */
    public void unscheduleDrawable(Drawable who, Runnable what) {
        if (callbackEnabled) {
            super.unscheduleDrawable(who, what);
        }
    }
}
Run Code Online (Sandbox Code Playgroud)


Nik*_*ber 6

检查 Nick Butcher 解决方案:
https://gist.github.com/nickbutcher/4179642450db266f0a33837f2622ace3
将 TileDrawable 类添加到您的项目中,然后将平铺可绘制对象设置为您的图像视图:

// after view created
val d = ContextCompat.getDrawable(this, R.drawable.pattern)
imageView.setImageDrawable(TileDrawable(d, Shader.TileMode.REPEAT))
Run Code Online (Sandbox Code Playgroud)