Draw a bitmap tiled across a Rect android
Asked Answered
M

2

7

I am attempting to draw a bitmap along a rectangle, but I am not sure how to go about it. Is there a way to tile a bitmap along a Rect object using a paint property or something? I have looked, but I can't find anything that makes it do what I need it too, most of the tiling options won't tile it for a specific instance, they tile it along the entire screen, so everything using that bitmap ends up having one big bitmap tiling along all of them at the same time, without scrolling or anything.

Any ideas? If you need more info let me know, its kind of a weird question so I know I probably didn't mention something important.

William

Maxillary answered 13/7, 2012 at 14:7 Comment(0)
S
13

There are a couple ways that you can attack this. I'll outline two of them here...

One way:

You can define a BitmapDrawable around the Bitmap. Set its TileMode to repeat. Give it some bounds via setBounds(rect) where rect is your Rect instance.

Here's a brief example using a View onDraw as context:

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

Note:

You can also define a BitmapDrawable in xml instead of doing it in code.

Also, if you know that a drawable you are loading via getResources().getDrawable(resourceId) is indeed just a Bitmap, you can cast it to a BitmapDrawable and set the TileMode there. A la:

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

This example shows the background being stretched, and a tiled version being draw over top of it.

Another way:

Loop in the x and y direction and repeatedly draw the bitmap into the rect:

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

I personally would go for the first (BitmapDrawable) method.

Salgado answered 13/7, 2012 at 15:0 Comment(3)
Alright, I will try both of these when I get home, thanks a lot!Maxillary
I know it's an old question but, why the first way is the best? more performance?Stets
More performance, as well as decreasing the amount of calls to canvas.drawBitmap. I'm using this in a game and it's amazing how well the game runs now, even in debug mode.Mojgan
E
5

You can do it just like BitmapDrawable does:

Define Paint with bitmap shader and then draw rectangle with that paint:

>     Paint paint = new Paint();
>     paint.setShader(new BitmapShader(bitmap, Shader.TileMode.REPEAT, Shader.TileMode.REPEAT));
>     
>     canvas.drawRect(destRect, paint);
Enunciation answered 21/9, 2015 at 1:36 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.