Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Make bitmap drawable tile in x but stretch in y

I have an image which I'm using as a background for a RelativeLayout. The image needs to be tiled horizontally to make a pattern.

I'm able to get the image to tile horizontally by using this code:

BitmapDrawable b3 = (BitmapDrawable)getResources().getDrawable(R.drawable.background);

b3.setTileModeX(Shader.TileMode.REPEAT);

v.findViewById(R.id.layout).setBackgroundDrawable(b3);

The problem is that the image also tiles vertically. It seems to tile in the "clamp" mode in the vertical, but "repeat" mode in the horizontal. Here is a screenshot:

TileMode

As you can see, the image is just a little bit smaller than the space it occupies, and the bottom edge is "clamped".

How can I set the image to stretch vertically but tile horizontally?

like image 257
howettl Avatar asked Sep 16 '11 21:09

howettl


3 Answers

This method invokes creation of new bitmap but it looks like it's acrhiving your goal

        View view = findViewById(R.id.layout);
        BitmapDrawable bd = (BitmapDrawable) getResources().getDrawable(R.drawable.tile);
        int width = view.getWidth();
        int intrinsicHeight = bd.getIntrinsicHeight();
        Rect bounds = new Rect(0,0,width,intrinsicHeight);
        bd.setTileModeX(TileMode.REPEAT);
        bd.setBounds(bounds);
        Bitmap bitmap = Bitmap.createBitmap(bounds.width(), bounds.height(), bd.getBitmap().getConfig());
        Canvas canvas = new Canvas(bitmap);
        bd.draw(canvas);
        BitmapDrawable bitmapDrawable = new BitmapDrawable(getResources(), bitmap);
        view.setBackground(bitmapDrawable);

Please note that it only works if view was already layouted, so a method lile onWindowFocusChanged is a good place for this code.

like image 103
Nikolay Ivanov Avatar answered Oct 20 '22 05:10

Nikolay Ivanov


I feel it is straight forward:(This code will tile in Y and repeat in x)

In your onWindowFoucsChanged you call:

 public void onWindowFocusChanged(boolean hasFocus) {
        // TODO Auto-generated method stub
        super.onWindowFocusChanged(hasFocus);
        Drawable d = getRepeatingBG(this, R.drawable.image_that_you_want_to_repeat);
        body_view.setBackgroundDrawable(d);

    }

private Drawable getRepeatingBG(Activity activity, int center)
    {   

        DisplayMetrics dm = new DisplayMetrics();
        activity.getWindowManager().getDefaultDisplay().getMetrics(dm);

        BitmapFactory.Options options = new BitmapFactory.Options();
        options.inScaled=true;

        Bitmap center_bmp = BitmapFactory.decodeResource(activity.getResources(), center, options);
        center_bmp.setDensity(Bitmap.DENSITY_NONE);
        center_bmp=Bitmap.createScaledBitmap(center_bmp, dm.widthPixels , center_bmp.getHeight(), true);

        BitmapDrawable center_drawable = new BitmapDrawable(activity.getResources(),center_bmp);
//change here setTileModeY to setTileModeX if you want to repear in X
        center_drawable.setTileModeY(Shader.TileMode.REPEAT);

        return center_drawable;
    }
like image 22
Ali Ashraf Avatar answered Oct 20 '22 05:10

Ali Ashraf


Far too late for you, but may be useful for others.

You can create a custom View in order to do this. Simply scale your source bitmap to be as high as your view and then draw it repeatedly on the canvas:

public class RepeatingXImageView extends View {

Bitmap bitmap;
Paint paint;

public RepeatingXImageView(Context context) {
    super(context);
}

public RepeatingXImageView(Context context, AttributeSet attrs) {
    super(context, attrs);
}

public RepeatingXImageView(Context context, AttributeSet attrs, int defStyleAttr) {
    super(context, attrs, defStyleAttr);
}

@Override
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
    super.onLayout(changed, left, top, right, bottom);
    if(changed) {
        paint = new Paint();
        bitmap = BitmapFactory.decodeResource(getContext().getResources(), R.drawable.seekbar_overlay);
        bitmap = Bitmap.createScaledBitmap(bitmap, bitmap.getWidth(), bottom - top, false);
    }
}

@Override
protected void onDraw(Canvas canvas) {
    super.onDraw(canvas);
    if(bitmap == null) return;
    int left = 0;
    while(left < getWidth()) {
        canvas.drawBitmap(bitmap, left, 0, paint);
        left += bitmap.getWidth();
    }
}
}
like image 29
Graeme Avatar answered Oct 20 '22 07:10

Graeme