Question

I want to set a background of a View with a tiled bitmap, but the tiling needs to be anchored to the bottom-left, instead of the top-left corner (the default). For example, if the tiles are the smiley faces below, I want it to be tiled like:

enter image description here

Using xml drawables I could achieve either tiling (using tileMode="repeat") or bottom positioning (using gravity="bottom"), but combining both is not possible, even the documentation says so:

android:tileMode

Keyword. Defines the tile mode. When the tile mode is enabled, the bitmap is repeated. Gravity is ignored when the tile mode is enabled.

Although it's not internally supported, is there any way to achieve this, perhaps using custom views?

Was it helpful?

Solution

Another way would be to extend BitmapDrawable and override the paint() method:

In this method we avoid creating a new bitmap having the size of the view.

class MyBitmapDrawable extends BitmapDrawable {
    private Paint mPaint = new Paint(Paint.FILTER_BITMAP_FLAG | Paint.DITHER_FLAG);
    private boolean mRebuildShader = true;
    private Matrix mMatrix = new Matrix();

    @Override
    public void draw(Canvas canvas) {
        Bitmap bitmap = getBitmap();
        if (bitmap == null) {
            return;
        }

        if (mRebuildShader) {
            mPaint.setShader(new BitmapShader(bitmap, TileMode.REPEAT, TileMode.REPEAT));
            mRebuildShader = false;
        }

        // Translate down by the remainder
        mMatrix.setTranslate(0, getBounds().bottom % getIntrinsicHeight());
        canvas.save();
        canvas.setMatrix(mMatrix);
        canvas.drawRect(getBounds(), mPaint);
        canvas.restore();
    }
}

It can be set to the view like this:

view.setBackgroundDrawable(new MyBitmapDrawable(getResources().getDrawable(R.drawable.smiley).getBitmap()));

OTHER TIPS

Just a thought, and it's pretty roundabout, but could you flip your image vertically, and then apply a transform to your background to flip that vertically as well?

Using a custom view might involve handling all the drawing yourself, not just the background image.

Instead, I propose to set the view's background programmatically as shown:

// This drawable refers to an image directly and NOT an XML
BitmapDrawable smiley = (BitmapDrawable) getResources().getDrawable(R.drawable.smiley);

// Create a new bitmap with the size of the view
Bitmap bgBitmap = Bitmap.createBitmap(view.getWidth(), view.getHeight(), Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(bgBitmap);

// Translate down by the remainder
Matrix matrix = new Matrix();
matrix.setTranslate(0, view.getHeight() % smiley.getIntrinsicHeight());
canvas.setMatrix(matrix);

// Tile the smileys
Paint paint = new Paint();
paint.setShader(new BitmapShader(smiley.getBitmap(), TileMode.REPEAT, TileMode.REPEAT));
canvas.drawPaint(paint);

view.setBackgroundDrawable(new BitmapDrawable(bgBitmap));

Points to consider:

  • I'm not sure if view.getWidth() & view.getHeight() are the correct methods to get the dimensions.
  • What if smiley size is bigger than the view?
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top