在 Android 中绘制一个平铺在矩形区域上的位图

7
我正尝试在矩形上绘制位图,但不确定如何处理。是否有一种使用画笔属性或其他方式沿Rect对象平铺位图的方法?我已经查过了,但找不到任何使其实现我所需功能的东西,大多数平铺选项都无法针对特定实例进行平铺,它们会沿着整个屏幕平铺,因此使用该位图的所有内容最终都会同时平铺一个大型位图,而没有滚动等功能。

您有什么想法吗?如果您需要更多信息,请告诉我,这可能是一个奇怪的问题,所以我知道我可能没有提到重要的内容。

威廉

2个回答

13

你可以采用两种方法来解决这个问题。下面我将概述其中的两种方法...

第一种方式:

你可以在Bitmap周围定义一个BitmapDrawable,并将其TileMode设置为repeat。通过setBounds(rect)方法为其设置一些边界,其中rect是你的矩形实例。

以下是一个简单的示例,使用View onDraw作为上下文:

public class MyView extends View {
    Rect rect;
    Bitmap mBitmap;
    BitmapDrawable mDrawable;

    public MyView(Context context) {
        super(context);
        rect = new Rect(0, 0, 100, 100);
        mBitmap = loadBitmap();
        mDrawable = new BitmapDrawable(context.getResources(), mBitmap);
        mDrawable.setTileModeXY(TileMode.REPEAT, TileMode.REPEAT);
        mDrawable.setBounds(rect);
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        mDrawable.draw(canvas);
    }

    public Bitmap loadBitmap() {
        // included only for example sake
        Paint paint = new Paint();
        paint.setColor(Color.RED);
        Bitmap bm = Bitmap.createBitmap(10, 10, Bitmap.Config.ARGB_8888);
        Canvas canvas = new Canvas(bm);
        canvas.drawRect(0,0,10,10, paint);
        paint.setStyle(Style.STROKE);
        paint.setColor(Color.BLUE);
        canvas.drawRect(0, 0, 9, 9, paint);
        return bm;
    }
}

注意:

你也可以在XML中定义BitmapDrawable而不是在代码中实现。

此外,如果你知道通过getResources().getDrawable(resourceId)加载的drawable确实只是一个Bitmap,则可以将其转换为BitmapDrawable并在那里设置TileMode。如下所示:

public class MyView extends View {
    Rect rect;
    BitmapDrawable mDrawable;

    public MyView(Context context) {
        super(context);
        rect = new Rect(0, 0, 400, 240);
        mDrawable = (BitmapDrawable) context.getResources().getDrawable(R.drawable.ic_launcher);
        mDrawable.setTileModeXY(TileMode.REPEAT, TileMode.REPEAT);
        mDrawable.setBounds(rect);

        this.setBackgroundDrawable(context.getResources().getDrawable(R.drawable.ic_launcher));
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        mDrawable.draw(canvas);
    }
}

这个示例展示了背景图片被拉伸,然后在其上方绘制了平铺版本。

另一种方法:

在x和y方向循环,并将位图重复地绘制到矩形中:

public class MyView extends View {
    Rect rect;
    Bitmap mBitmap;

    public MyView(Context context) {
        super(context);
        rect = new Rect(0, 0, 100, 100);
        mBitmap = loadBitmap();
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        final int bmWidth = mBitmap.getWidth();
        final int bmHeight = mBitmap.getHeight();

        for (int y = 0, height = rect.height(); y < height; y += bmHeight) {
            for (int x = 0, width = rect.width(); x < width; x += bmWidth) {
                canvas.drawBitmap(mBitmap, x, y, null);
            }
        }
    }

    public Bitmap loadBitmap() {
        // included only for example sake
        Paint paint = new Paint();
        paint.setColor(Color.RED);
        Bitmap bm = Bitmap.createBitmap(10, 10, Bitmap.Config.ARGB_8888);
        Canvas canvas = new Canvas(bm);
        canvas.drawRect(0,0,10,10, paint);
        paint.setStyle(Style.STROKE);
        paint.setColor(Color.BLUE);
        canvas.drawRect(0, 0, 9, 9, paint);
        return bm;
    }
}

个人而言,我会选择第一种方法(BitmapDrawable)。


好的,我回家后会尝试这两个,非常感谢! - William Hoskins
我知道这是一个老问题,但是为什么第一种方式是最好的呢?更高的性能吗? - Moondustt
更高的性能,以及减少对canvas.drawBitmap的调用次数。我在游戏中使用它,惊讶于现在游戏的运行效果,即使在调试模式下也是如此。 - Robson França

5
您可以像BitmapDrawable一样操作:

使用位图着色器定义画笔,然后使用该画笔绘制矩形:

>     Paint paint = new Paint();
>     paint.setShader(new BitmapShader(bitmap, Shader.TileMode.REPEAT, Shader.TileMode.REPEAT));
>     
>     canvas.drawRect(destRect, paint);

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接