避免 android 样式中的重复代码
Avoiding duplicated code in android styles
我有一个 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>
我想知道这种方法的缺点是什么。
您可以使用打开版本限定符的维度资源修复原始重复问题,然后在样式中引用它:
<!-- 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>
正如@DanielLew 回答的那样,仅覆盖xml 值文件中的dimen/color/drawable 值是为不同Android 版本或更改某些样式项目的最佳方式屏幕尺寸。
当您必须覆盖新 Android 版本以使用新视图 属性(android:layout_marginStart
for v17)时,样式变得更加复杂且难以支持。在这种情况下,我建议 提取基本样式 并将其用作默认值和新版本值(例如 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。
您两次(显式和隐式)设置了父级,这增加了额外的混乱。阅读 link 中的 Implicit vs. Explicit Parenting
部分。
我有一个 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>
我想知道这种方法的缺点是什么。
您可以使用打开版本限定符的维度资源修复原始重复问题,然后在样式中引用它:
<!-- 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>
正如@DanielLew 回答的那样
当您必须覆盖新 Android 版本以使用新视图 属性(android:layout_marginStart
for v17)时,样式变得更加复杂且难以支持。在这种情况下,我建议 提取基本样式 并将其用作默认值和新版本值(例如 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。
您两次(显式和隐式)设置了父级,这增加了额外的混乱。阅读 link 中的 Implicit vs. Explicit Parenting
部分。