简体   繁体   English

在Android上重用drawable的部分内容

[英]Reusing parts of drawable on Android

I'm preparing drawables for my application. 我正在为我的应用准备drawables。 I've got a lot of radiobuttons, which are being displayed as images with optional frame (when checked). 我有很多单选按钮,它们显示为带有可选框架的图像(选中时)。 One drawable looks like the following: 一个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>

Another one: 另一个:

<?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>

If you don't wanna play "find 2 differences", the only thing that changes is the image in <bitmap> tag. 如果你不想玩“找到2个差异”,唯一改变的是<bitmap>标签中的图像。

I'm feeling whole WET 1 here. 我在这里感觉整个WET 1 Is there a way to reuse part of this drawable? 有没有办法重用这个drawable的一部分?

1 WET, eg. 1 WET,例如。 not DRY 不干

In short: There are no parameters for XML drawables, thus this might get a bit complicated. 简而言之:XML drawable没有参数,因此可能会有点复杂。

Usually 1 I would try to separate all the single <item> contents into separate drawable files and then include them with <item android:drawable="..." /> . 通常1我会尝试将所有单个<item>内容分成单独的可绘制文件,然后用<item android:drawable="..." />包含它们。 Those can then reused in other drawables. 那些可以在其他drawables中重复使用。

For example you could move the following item into a separate file: 例如,您可以将以下项目移动到单独的文件中:

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

Then you can include (reuse) it anywhere it is needed: 然后,您可以在需要的任何地方包含(重用)它:

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

1 In your case however you might only save ~10% by using this approach since the <bitmap> elements are buried deep in the hierarchy. 1但是,在您的情况下,使用此方法可能只能节省~10%,因为<bitmap>元素深埋在层次结构中。


Another, slightly exotic approach would be using a Gradle task to generate multiple XML drawables from a single drawable template. 另一种略带异国情调的方法是使用Gradle任务从单个可绘制模板生成多个XML drawable。 This obviously requires that you use Gradle or Android Studio respectively. 这显然要求您分别使用Gradle或Android Studio。

You can put your drawable file into the /res/raw folder (or any other folder that doesn't cause problems). 您可以将可绘制文件放入/res/raw文件夹(或任何其他不会导致问题的文件夹)。 I'll name this XML template file drawable_template.xml as referenced below. 我将这个XML模板文件命名为drawable_template.xml ,如下所述。 In this file we use a Groovy template variable ${bitmapdrawable} as the placeholder for your actual bitmap drawable's name: 在这个文件中,我们使用Groovy模板变量${bitmapdrawable}作为实际位图drawable名称的占位符:

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

Now we need to define a Gradle task to copy the drawable template to the actual /res/drawable folder with the desired bitmap drawables included: 现在我们需要定义一个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

That script can be put into the app's (module's) build.gradle file. 该脚本可以放入应用程序(模块)的build.gradle文件中。

Now the final drawables with the different included bitmaps are generated from a single template file at compile time. 现在,在编译时从单个模板文件生成具有不同包含的位图的最终drawable。 They have the name drawable_gen_sharpX.xml and can be used as normal drawables. 它们的名称为drawable_gen_sharpX.xml ,可用作普通的drawable。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM