在Android上重用drawable的部分内容

时间:2016-01-19 20:34:42

标签: android android-drawable

我正在为我的应用程序准备drawables。我有很多单选按钮,它们显示为带有可选框架的图像(选中时)。一个drawable如下所示:

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:state_checked="true">
        <layer-list>
            <item>
                <shape android:shape="rectangle">
                    <solid android:color="@color/colorPrimary" />
                </shape>
            </item>

            <item>
                <inset android:insetTop="@dimen/selectionBorderSize"
                    android:insetLeft="@dimen/selectionBorderSize"
                    android:insetRight="@dimen/selectionBorderSize"
                    android:insetBottom="@dimen/selectionBorderSize">
                    <layer-list>
                        <item>
                            <shape android:shape="rectangle">
                                <solid android:color="#ffffff"></solid>
                            </shape>
                        </item>
                        <item>
                            <bitmap android:src="@drawable/sharp7" >
                                <padding android:bottom="@dimen/selectionBorderSize"
                                    android:top="@dimen/selectionBorderSize"
                                    android:left="@dimen/selectionBorderSize"
                                    android:right="@dimen/selectionBorderSize" />
                            </bitmap>
                        </item>
                    </layer-list>
                </inset>
            </item>
        </layer-list>
    </item>

    <item android:state_checked="false">
        <layer-list>
            <item>
                <shape android:shape="rectangle">
                    <solid android:color="#ffffff" />
                </shape>
            </item>

            <item>
                <inset android:insetTop="@dimen/selectionBorderSize"
                    android:insetLeft="@dimen/selectionBorderSize"
                    android:insetRight="@dimen/selectionBorderSize"
                    android:insetBottom="@dimen/selectionBorderSize">
                    <layer-list>
                        <item>
                            <shape android:shape="rectangle">
                                <solid android:color="#ffffff"></solid>
                            </shape>
                        </item>
                        <item>
                            <bitmap android:src="@drawable/sharp7" >
                                <padding android:bottom="@dimen/selectionBorderSize"
                                    android:top="@dimen/selectionBorderSize"
                                    android:left="@dimen/selectionBorderSize"
                                    android:right="@dimen/selectionBorderSize" />
                            </bitmap>
                        </item>
                    </layer-list>
                </inset>
            </item>
        </layer-list>
    </item>

    <item>
        <shape android:shape="rectangle">
            <solid android:color="#ffffff" />
        </shape>
    </item>
</selector>

另一个:

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:state_checked="true">
        <layer-list>
            <item>
                <shape android:shape="rectangle">
                    <solid android:color="@color/colorPrimary" />
                </shape>
            </item>

            <item>
                <inset android:insetTop="@dimen/selectionBorderSize"
                    android:insetLeft="@dimen/selectionBorderSize"
                    android:insetRight="@dimen/selectionBorderSize"
                    android:insetBottom="@dimen/selectionBorderSize">
                    <layer-list>
                        <item>
                            <shape android:shape="rectangle">
                                <solid android:color="#ffffff"></solid>
                            </shape>
                        </item>
                        <item>
                            <bitmap android:src="@drawable/sharp6" >
                                <padding android:bottom="@dimen/selectionBorderSize"
                                    android:top="@dimen/selectionBorderSize"
                                    android:left="@dimen/selectionBorderSize"
                                    android:right="@dimen/selectionBorderSize" />
                            </bitmap>
                        </item>
                    </layer-list>
                </inset>
            </item>
        </layer-list>
    </item>

    <item android:state_checked="false">
        <layer-list>
            <item>
                <shape android:shape="rectangle">
                    <solid android:color="#ffffff" />
                </shape>
            </item>

            <item>
                <inset android:insetTop="@dimen/selectionBorderSize"
                    android:insetLeft="@dimen/selectionBorderSize"
                    android:insetRight="@dimen/selectionBorderSize"
                    android:insetBottom="@dimen/selectionBorderSize">
                    <layer-list>
                        <item>
                            <shape android:shape="rectangle">
                                <solid android:color="#ffffff"></solid>
                            </shape>
                        </item>
                        <item>
                            <bitmap android:src="@drawable/sharp6" >
                                <padding android:bottom="@dimen/selectionBorderSize"
                                    android:top="@dimen/selectionBorderSize"
                                    android:left="@dimen/selectionBorderSize"
                                    android:right="@dimen/selectionBorderSize" />
                            </bitmap>
                        </item>
                    </layer-list>
                </inset>
            </item>
        </layer-list>
    </item>

    <item>
        <shape android:shape="rectangle">
            <solid android:color="#ffffff" />
        </shape>
    </item>
</selector>

如果你不想玩“找到2个差异”,唯一改变的是<bitmap>标签中的图像。

我在这里感觉整个WET 1 。有没有办法重用这个drawable的一部分?

1 WET,例如。不是DRY

1 个答案:

答案 0 :(得分:11)

简而言之:XML drawable没有参数,因此可能会有点复杂。

通常 1 我会尝试将所有单个<item>内容分成单独的可绘制文件,然后将它们包含在<item android:drawable="..." />中。那些可以在其他绘图中重复使用。

例如,您可以将以下项目移动到单独的文件中:

<item>
    <shape android:shape="rectangle">
        <solid android:color="#ffffff" />
    </shape>
</item>

然后,您可以在任何需要的地方包含(重复使用):

<item android:drawable="@drawable/shared_drawable" />

1 但是,在您的情况下,您可能只使用此方法节省约10%,因为<bitmap>元素深埋在层次结构中。

另一种略带异国情调的方法是使用Gradle任务从单个可绘制模板生成多个XML drawable。这显然要求您分别使用Gradle或Android Studio。

您可以将可绘制文件放入/res/raw文件夹(或任何其他不会导致问题的文件夹)。我将这个XML模板文件命名为drawable_template.xml,如下所述。在此文件中,我们使用Groovy模板变量${bitmapdrawable}作为实际位图drawable名称的占位符:

...
    <item>
        <bitmap android:src="@drawable/${bitmapdrawable}"><!-- placeholder for gradle -->
            ...
        </bitmap>
    </item>
...

现在我们需要定义一个Gradle任务,将drawable模板复制到实际的/res/drawable文件夹,其中包含所需的位图drawable:

def drawablesToGenerate = ['sharp5', 'sharp6', 'sharp7', 'sharp8']  // bitmap names
task drawableTemplate << {
    drawablesToGenerate.each { drawableName ->  // for each drawable
        copy {
            println("copy template for ${drawableName}")
            from 'src/main/res/raw'  // source folder
            into 'src/main/res/drawable'  // target folder
            include 'drawable_template.xml'  // template file
            // rename file to final drawable
            rename('drawable_template.xml', "drawable_gen_${drawableName}.xml")
            expand(bitmapdrawable: "${drawableName}")
        }
    }
}
preBuild.dependsOn drawableTemplate

该脚本可以放入应用程序(模块)build.gradle文件中。

现在,在编译时从单个模板文件生成包含不同包含位图的最终drawable。它们的名称为drawable_gen_sharpX.xml,可以用作普通的drawable。