避免在android样式

时间:2015-08-04 22:22:15

标签: android styles duplication

我有一个Android应用程序,支持api 14和目标api 21.我有一些样式需要被api 21覆盖。会发生的是我需要复制所有样式项只是为了更改一个项目。

例如:

<!-- values/styles.xml -->

<style name="Widget.HelloWorld.Button">
    <item name="android:textSize">24sp</item>
    <item name="android:drawableLeft">@android:drawable/ic_menu_delete</item>
</style>

如果我只想覆盖api 21中的属性android:textSize,我也需要复制项目android:drawableLeft

为了避免这种情况,我找到了解决方案。在此示例中,我有三个按钮(foobarfancy),其中包含一些样式(Widget.HelloWorld.Button.FooWidget.HelloWorld.Button.BarWidget.HelloWorld.Button.Fancy

<!-- values/styles.xml -->

<resources>
    <style name="v0.Widget.HelloWorld.Button" parent="Widget.AppCompat.Button">
        <item name="android:textSize">24sp</item>
        <item name="android:drawableLeft">@android:drawable/ic_menu_delete</item>
    </style>

    <style name="v0.Widget.HelloWorld.Button.Foo" parent="Widget.HelloWorld.Button">
        <item name="android:textColor">#f00</item>
    </style>

    <style name="v0.Widget.HelloWorld.Button.Bar" parent="Widget.HelloWorld.Button">
        <item name="android:textColor">#ff0</item>
    </style>

    <style name="v0.Widget.HelloWorld.Button.Fancy" parent="Widget.HelloWorld.Button">
        <item name="android:textColor">#f0f</item>
    </style>

    <!-- Alias -->
    <style name="Widget.HelloWorld.Button" parent="v0.Widget.HelloWorld.Button" />
    <style name="Widget.HelloWorld.Button.Foo" parent="v0.Widget.HelloWorld.Button.Foo" />
    <style name="Widget.HelloWorld.Button.Bar" parent="v0.Widget.HelloWorld.Button.Bar" />
    <style name="Widget.HelloWorld.Button.Fancy" parent="v0.Widget.HelloWorld.Button.Fancy" />
</resources>

我在所有样式名称前面加上了会产生影响的api的版本号。由于values/styles.xml是默认值,我的前缀是v0

现在在values-v21/styles.xml我可以覆盖我想要的项目,而无需重复代码。

<!-- values-v21/styles.xml -->

<resources>
    <style name="v21.Widget.HelloWorld.Button" parent="v0.Widget.HelloWorld.Button">
        <item name="android:textSize">36sp</item>
    </style>

    <style name="v21.Widget.HelloWorld.Button.Fancy" parent="v0.Widget.HelloWorld.Button.Fancy">
        <item name="android:colorPrimary">@color/primary</item>
    </style>

    <!-- Alias -->
    <style name="Widget.HelloWorld.Button" parent="v21.Widget.HelloWorld.Button" />
    <style name="Widget.HelloWorld.Button.Fancy" parent="v21.Widget.HelloWorld.Button.Fancy" />
</resources>

我想知道这种方法的缺点是什么。

2 个答案:

答案 0 :(得分:2)

您可以使用打开版本限定符的维度资源修复原始复制问题,然后以样式引用它:

<!-- values/dimens.xml -->
<resource>
    <dimen name="hello_text_size">24sp</dimen>
</resource>

<!-- values-v21/dimens.xml -->
<resource>
    <dimen name="hello_text_size">36sp</dimen>
</resource>

<!-- values/styles.xml -->
<style name="Widget.HelloWorld.Button">
    <item name="android:textSize">@dimen/hello_text_size</item>
    <item name="android:drawableLeft">@android:drawable/ic_menu_delete</item>
</style>

答案 1 :(得分:1)

@DanielLew回答here时,只覆盖xml值文件中的dimen / color / drawable值是更改不同Android版本或屏幕大小的某些样式项的最佳方法。

当你必须为新的Android版本覆盖它以使用新的View属性(v {的android:layout_marginStart)时,样式变得更加复杂和难以支持。在这种情况下,我建议提取基本样式,并将其用作默认值和新版本值(示例中的v17)文件夹中样式的父级。

<!-- values/dimens.xml -->
<resource>
    <dimen name="button_text_size">24sp</dimen>
    <dimen name="margin_size">10dp</dimen>
</resource>

<!-- values/styles.xml -->
<resources>
    <!-- Parent style - add all common properties -->
    <style name="Widget.HelloWorld.Button" parent="Widget.AppCompat.Button">
        <item name="android:textSize">@dimen/button_text_size</item>
        <item name="android:drawableLeft">@android:drawable/ic_menu_delete</item>
    </style>

    <!-- Child style - add version specific properties (minimum version) -->
    <style name="Widget.HelloWorld.Button.Foo">
        <item name="android:layout_marginLeft">@dimen/margin_size</item>
    </style>
<resources>

<!-- values-v17/styles.xml - minimum version for the new property -->
<resources>
    <!-- Child style - add version specific properties (v17) -->
    <style name="Widget.HelloWorld.Button.Foo">
        <item name="android:layout_marginStart">@dimen/margin_size</item>
    </style>
<resources>

请阅读Styling Views on Android。 您设置父级两次(显式和隐式),这会增加额外的混淆。从链接中阅读Implicit vs. Explicit Parenting部分。