我认为将属性声明为可样式化与否只有以下区别。
在 attrs.xml 中,您可以直接在“resources”部分或“declare-styleable”中声明自定义属性:
<?xml version="1.0" encoding="utf-8"?>
<resources>
<attr name="attrib1" format="string" />
<declare-styleable name="blahblah">
<attr name="attrib2" format="string" />
</declare-styleable>
所以现在我们将“attrib1”定义为不可样式化,将“attrib2”定义为可样式化。
在layout/someactivity.xml 中我们可以直接使用这些属性(不需要命名空间):
<com.custom.ViewClass attrib1="xyz" attrib2="abc"/>
您可以在style.xml 声明中使用“styleable”属性“attrib2”。同样,这里不需要命名空间(即使在布局 XML 中使用了命名空间)。
<style name="customstyle" parent="@android:style/Widget.TextView">
<item name="attrib2">text value</item>
<!-- customize other, standard attributes too: -->
<item name="android:textColor">@color/white</item>
</style>
然后你也可以设置每个样式的属性。
<com.custom.CustomView attrib1="xyz" style="@style/customstyle"/>
假设我们这样做:我们直接在 XML 中设置attrib1,我们在样式中设置attrib2。
我在其他地方看到过说明“blahblah”必须是使用这些属性的自定义视图类的名称,并且您需要使用命名空间来引用布局 XML 中的自定义属性。但这些似乎都没有必要。
styleable 和 non-styleable 的区别似乎在于:
- 您可以在“
style.xml”声明中使用可设置样式的属性。
- 自定义类的构造函数需要以不同的方式读取样式属性和非样式属性:样式属性为
obtainStyledAttributes(),非样式属性为attr.getAttributeValue()或类似。
在我在网上看到的大多数教程和示例中,只使用了obtainStyledAttributes()。但是,这不适用于直接在布局中声明的属性,而不使用样式。如果你像大多数教程中所示的那样做obtainStyledAttributes(),你根本不会得到属性attrib1;你只会得到attrib2,因为它是在样式中声明的。使用attr.getAttributeValue() 的直接方法有效:
public CustomView(Context context, AttributeSet attrs) {
super(context, attrs);
String attrib1 = attrs.getAttributeValue(null, "attrib1");
// do something with this value
}
由于我们没有使用命名空间来声明“attrib1”,因此我们将 null 作为命名空间参数传递给 getAttributeValue()。