【问题标题】:Android - Drawable repeat shape to create patternAndroid - 可绘制重复形状以创建图案
【发布时间】:2016-04-20 15:14:44
【问题描述】:

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

我不想将任何图像导入可绘制对象,而是想创建自己的形状、图层列表,最终目标是将图案作为背景。

是否可以在不导入任何外部图像的情况下实现这一目标?

【问题讨论】:

    标签: android android-drawable shapes


    【解决方案1】:

    您可以通过创建自定义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() 的调用
    • 对于许多Views,将您的自定义View 置于另一个View 下方(例如作为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);
    }
    

    编辑

    如上所述,在某些情况下(例如TextViewProgressBar)您可能需要使用解决方法:

    • 使您的View 背景透明。
    • 使用图案作为背景创建自定义布局。
    • View 包裹在自定义布局中(将布局宽度和高度设置为wrap_content)。

    【讨论】:

    • 很好的答案!还有一个问题。我正在尝试将此自定义背景设置为进度条。我无法保留前景,所以我看不到进度,只能看到它自己的背景。你能给我一些关于 onDraw() 方法的提示吗?
    • 我创建了新问题,与我的问题的下一步有关。请查看stackoverflow.com/questions/36765444/…
    • @Bugdr0id - 这是我认为使用一些解决方法实际上更容易的情况之一。例如,您可以将背景模式与 FrameLayout 或 RelativeLayout(宽度和高度与 ProgressBar 大小匹配)一起使用,然后将 Progressbar(具有透明背景)作为此布局的唯一子项。
    猜你喜欢
    • 1970-01-01
    • 2019-03-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-11-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多