Android - 可绘制重复形状以创建图案
Android - Drawable repeat shape to create pattern
我需要创建一个图案来设置为某些 View
的背景。我希望图案看起来像这样:
我不想将任何图像导入可绘制对象,而是想创建自己的形状、图层列表,最终目标是将图案作为背景。
是否可以在不导入任何外部图像的情况下实现这一点?
您可以通过创建自定义 View
并覆盖 onDraw()
.
来获得基于可绘制形状的重复图块的图案
让我们首先将图块创建为由形状可绘制对象组成的图层列表,在本例中为黑白交替的方块:
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>
您需要一种方法 drawableToBitmap()
将图块转换为像 here 这样的位图。
覆盖 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);
}
}
根据 View
的类型,您可能需要采取额外的步骤。
- 对于扩展某种
Layout
的自定义 View
,将 android:background
属性设置为任何颜色以触发对 onDraw()
[=66= 的调用]
- 对于许多
View
来说,将您的自定义 View
置于另一个 View
之下可能更容易实施,同时性能更好(例如,作为两个 children in a RelativeLayout
) 并使大小匹配。
- 如果您想从
ImageView
扩展,您需要在背景图案之上绘制前景可绘制对象。这种情况下,可以修改onDraw()
如下:
onDraw() 保留前景可绘制对象:
@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);
}
编辑
如上所述,在某些情况下(例如 TextView
、ProgressBar
)您可能需要使用解决方法:
- 使您的
View
背景透明。
- 使用图案作为背景创建自定义布局。
- 在自定义布局中包裹
View
(将布局宽度和高度设置为 wrap_content
)。
我需要创建一个图案来设置为某些 View
的背景。我希望图案看起来像这样:
我不想将任何图像导入可绘制对象,而是想创建自己的形状、图层列表,最终目标是将图案作为背景。
是否可以在不导入任何外部图像的情况下实现这一点?
您可以通过创建自定义 View
并覆盖 onDraw()
.
让我们首先将图块创建为由形状可绘制对象组成的图层列表,在本例中为黑白交替的方块:
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>
您需要一种方法 drawableToBitmap()
将图块转换为像 here 这样的位图。
覆盖 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);
}
}
根据 View
的类型,您可能需要采取额外的步骤。
- 对于扩展某种
Layout
的自定义View
,将android:background
属性设置为任何颜色以触发对onDraw()
[=66= 的调用] - 对于许多
View
来说,将您的自定义View
置于另一个View
之下可能更容易实施,同时性能更好(例如,作为两个 children in aRelativeLayout
) 并使大小匹配。 - 如果您想从
ImageView
扩展,您需要在背景图案之上绘制前景可绘制对象。这种情况下,可以修改onDraw()
如下:
onDraw() 保留前景可绘制对象:
@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);
}
编辑
如上所述,在某些情况下(例如 TextView
、ProgressBar
)您可能需要使用解决方法:
- 使您的
View
背景透明。 - 使用图案作为背景创建自定义布局。
- 在自定义布局中包裹
View
(将布局宽度和高度设置为wrap_content
)。