I need to create a pattern to set as a background of some View
. I want the pattern to look something like this:
I don't want to import any image to drawable, but instead, I want to create my own shapes, layer-list and the ultimate goal is to have a pattern as a background.
Is is possible to achieve this without having to import any external image?
You can get a pattern of repeating tiles based upon shape drawables by creating a custom View
and overriding onDraw()
.
Let's start by creating the tile as a layer list made of shape drawables, in this case alternating squares of black and white:
my_background.xml
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item>
<layer-list>
<item >
<shape >
<solid android:color="#ffffff"/>
<size
android:height="8dp"
android:width="8dp"
/>
</shape>
</item>
<item android:left="4dp" android:top="4dp" android:bottom="0dp" android:right="0dp" >
<shape >
<solid android:color="#ff000000"/>
<size
android:height="4dp"
android:width="4dp"
/>
</shape>
</item>
<item android:left="0dp" android:top="0dp" android:bottom="4dp" android:right="4dp">
<shape>
<solid android:color="#ff000000"/>
<size
android:height="4dp"
android:width="4dp"
/>
</shape>
</item>
</layer-list>
</item>
You need a method drawableToBitmap()
to transform the tile into a Bitmap like here.
Override onDraw()
:
@Override
protected void onDraw(Canvas canvas)
{
super.onDraw(canvas);
Drawable d = getResources().getDrawable(R.drawable.my_background);
if (d != null)
{
Bitmap b = drawableToBitmap(d);
BitmapDrawable bm = new BitmapDrawable(getResources(), b);
bm.setTileModeXY(Shader.TileMode.REPEAT, Shader.TileMode.REPEAT);
bm.setBounds(canvas.getClipBounds());
bm.draw(canvas);
}
}
Depending on the type of View
, you may have to take additional steps.
View
extending some kind of Layout
, set the android:background
attribute to any color in order to trigger the call to onDraw()
View
s it may be easier to implement and at the same time better for performance to position your custom View
below the other View
(e.g. as two children in a RelativeLayout
) and make the sizes match.ImageView
you will need to draw the foreground drawable on top of the background pattern. In this case, you can modify onDraw()
as follows:onDraw() preserving foreground drawable:
@Override
protected void onDraw(Canvas canvas)
{
super.onDraw(canvas);
// preserve foreground drawable if there is one:
Drawable fd = getDrawable();
Drawable d = getResources().getDrawable(R.drawable.my_background);
if (d != null)
{
Bitmap b = drawableToBitmap(d);
BitmapDrawable bm = new BitmapDrawable(getResources(), b);
bm.setTileModeXY(Shader.TileMode.REPEAT, Shader.TileMode.REPEAT);
bm.setBounds(canvas.getClipBounds());
bm.draw(canvas);
}
if (fd == null)
return;
// set bounds as needed
fd.setBounds(0, 0, 100, 100);
fd.draw(canvas);
}
EDIT
As mentioned above, in some cases (e.g. TextView
, ProgressBar
) you may want to use a workaround:
View
background transparent.View
in the custom layout (set the layout width and height to wrap_content
).If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With