如何为自定义小部件定义主题(样式)项目

我已经为我们在应用程序中广泛使用的控件编写了一个自定义小部件。 widget类从ImageButton派生,并以几种简单的方式扩展它。 我已经定义了一个可以应用到小部件的样式,但是我希望通过主题进行设置。 在R.styleable我看到了widget的style属性,比如imageButtonStyleimageButtonStyle 。 有什么办法可以为我写的自定义小部件创build类似的东西吗?

是的,有一个方法:

假设你有一个小部件的属性声明(在attrs.xml ):

 <declare-styleable name="CustomImageButton"> <attr name="customAttr" format="string"/> </declare-styleable> 

声明将用于样式引用的属性(在attrs.xml ):

 <declare-styleable name="CustomTheme"> <attr name="customImageButtonStyle" format="reference"/> </declare-styleable> 

为widget声明一组默认的属性值(在styles.xml ):

 <style name="Widget.ImageButton.Custom" parent="android:style/Widget.ImageButton"> <item name="customAttr">some value</item> </style> 

声明自定义主题(在themes.xml ):

 <style name="Theme.Custom" parent="@android:style/Theme"> <item name="customImageButtonStyle">@style/Widget.ImageButton.Custom</item> </style> 

在你的构件的构造函数中使用这个属性作为第三个参数(在CustomImageButton.java ):

 public class CustomImageButton extends ImageButton { private String customAttr; public CustomImageButton( Context context ) { this( context, null ); } public CustomImageButton( Context context, AttributeSet attrs ) { this( context, attrs, R.attr.customImageButtonStyle ); } public CustomImageButton( Context context, AttributeSet attrs, int defStyle ) { super( context, attrs, defStyle ); final TypedArray array = context.obtainStyledAttributes( attrs, R.styleable.CustomImageButton, defStyle, R.style.Widget_ImageButton_Custom ); // see below this.customAttr = array.getString( R.styleable.CustomImageButton_customAttr, "" ); array.recycle(); } } 

现在,您必须将Theme.Custom应用于使用CustomImageButton所有活动(在AndroidManifest.xml中):

 <activity android:name=".MyActivity" android:theme="@style/Theme.Custom"/> 

就这样。 现在, CustomImageButton尝试加载当前主题的customImageButtonStyle属性的默认属性值。 如果在主题中没有find这样的属性,或者属性的值是@null则在这种情况下将使用Widget.ImageButton.Custom的最后一个参数: Widget.ImageButton.Custom

您可以更改所有实例和所有文件( AndroidManifest.xml除外)的名称,但使用Android命名约定会更好。

除了迈克尔杰出的答案之外,另一个方面是重写主题中的自定义属性。 假设您有许多自定义视图都参考自定义属性“custom_background”。

 <declare-styleable name="MyCustomStylables"> <attr name="custom_background" format="color"/> </declare-styleable> 

在一个主题中,你定义了什么是价值

 <style name="MyColorfulTheme" parent="AppTheme"> <item name="custom_background">#ff0000</item> </style> 

要么

 <style name="MyBoringTheme" parent="AppTheme"> <item name="custom_background">#ffffff</item> </style> 

您可以引用样式中的属性

 <style name="MyDefaultLabelStyle" parent="AppTheme"> <item name="android:background">?background_label</item> </style> 

注意问号,也用于引用android属性

 ?android:attr/colorBackground 

正如大多数人已经注意到的,你可以 – 也许应该 – 使用@color引用而不是硬编码的颜色。

那么为什么不呢

 <item name="android:background">@color/my_background_color</item> 

您不能在运行时更改“my_background_color”的定义,而您可以轻松切换主题。