Android - 可绘制的重复形状来创建图案

Bug*_*0id 6 android shapes android-drawable

我需要创建一个模式来设置为某些模式的背景View.我希望模式看起来像这样:

图案

我不想将任何图像导入drawable,但相反,我想创建自己的形状,图层列表,最终目标是将图案作为背景.

是否有可能实现这一点,而无需导入任何外部图像?

0X0*_*gar 5

您可以通过创建自定义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>
Run Code Online (Sandbox Code Playgroud)

您需要一种方法drawableToBitmap()将切片转换为像这里的位图.

覆盖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);
    }
}
Run Code Online (Sandbox Code Playgroud)

根据类型View,您可能需要采取其他步骤.

  • 对于View某种类型的自定义Layout,将android:background属性设置为任何颜色以触发调用onDraw()
  • 对于许多人而言,View它可能更容易实现,同时更好地将性能定位View在另一个之下View(例如,作为两个孩子在一起RelativeLayout)并使大小匹配.
  • 如果要从中扩展,ImageView则需要在背景图案的顶部绘制前景drawable.在这种情况下,您可以修改onDraw()如下:

onDraw()保留前景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);
}
Run Code Online (Sandbox Code Playgroud)

编辑

在某些情况下上面提到的,(例如TextView,ProgressBar),你可能想使用一种变通方法:

  • 让你的View背景透明.
  • 使用模式作为背景创建自定义布局.
  • View自定义布局包装(将布局宽度和高度设置为wrap_content).