我有一个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
。
为了避免这种情况,我找到了解决方案。在此示例中,我有三个按钮(foo
,bar
和fancy
),其中包含一些样式(Widget.HelloWorld.Button.Foo
,Widget.HelloWorld.Button.Bar
,Widget.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>
我想知道这种方法的缺点是什么。
答案 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
部分。