Ted*_*opp 77 xml android styleable declare-styleable
关于declare-styleable标记的珍贵文档很少,我们可以通过它来声明组件的自定义样式.我确实找到了这个标签format属性的有效值列表attr.虽然这很好,但它没有解释如何使用其中的一些值.浏览attr.xml(标准属性的Android源代码),我发现你可以做以下事情:
<!-- The most prominent text color. -->
<attr name="textColorPrimary" format="reference|color" />
Run Code Online (Sandbox Code Playgroud)
该format属性显然可以设置为值的组合.据推测,该format属性有助于解析器解释实际的样式值.然后我在attr.xml中发现了这个:
<!-- Default text typeface. -->
<attr name="typeface">
<enum name="normal" value="0" />
<enum name="sans" value="1" />
<enum name="serif" value="2" />
<enum name="monospace" value="3" />
</attr>
<!-- Default text typeface style. -->
<attr name="textStyle">
<flag name="normal" value="0" />
<flag name="bold" value="1" />
<flag name="italic" value="2" />
</attr>
Run Code Online (Sandbox Code Playgroud)
这两个似乎都声明了一组指定样式的允许值.
所以我有两个问题:
enum值之一的样式属性与可以采用一组值的样式属性之间的区别是什么flag?declare-styleable工作(除逆向工程Android源代码)?Ale*_*dam 69
这里有一个问题:用一些信息定义定制的attrs,但不多.
这篇文章.它有关于标志和枚举的良好信息:
自定义XML属性标志
标志是特殊属性类型,因为它们只允许非常小的值子集,即在属性标记下定义的值.标志由"name"属性和"value"属性指定.名称在该属性类型中必须是唯一的,但值不必是.这就是在Android平台发展过程中我们将"fill_parent"和"match_parent"映射到相同行为的原因.他们的价值是相同的.
name属性映射到布局XML中值位置使用的名称,不需要名称空间前缀.因此,对于上面的"tilingMode",我选择"center"作为属性值.我可以轻松地选择"拉伸"或"重复",但没有别的.甚至不允许在实际值中替换.
value属性必须是整数.十六进制或标准数字表示的选择取决于您.Android代码中有一些地方使用了这两个地方,Android编译器很乐意接受.
自定义XML属性枚举
枚举以与具有一个规定的标志几乎相同的方式使用,它们可以与整数互换使用.在引擎盖下,枚举和整数映射到相同的数据类型,即整数.当使用整数出现在属性定义中时,枚举用于防止总是坏的"魔术数字".这就是为什么你可以使用带有维度,整数或命名字符串"fill_parent"的"android:layout_width".
为了把它放到上下文中,让我们假设我创建了一个名为"layout_scroll_height"的自定义属性,它接受一个整数或字符串"scroll_to_top".为此,我将添加一个"整数"格式属性,然后使用枚举:
Run Code Online (Sandbox Code Playgroud)<attr name="layout_scroll_height" format="integer"> <enum name="scroll_to_top" value="-1"/> </attr>以这种方式使用Enums时的一个规定是使用自定义View的开发人员可以有目的地将值"-1"放入布局参数中.这将触发"scroll_to_top"的特殊情况逻辑.如果选择Enum值很差,这种意外(或预期)行为可能会迅速将您的库转移到"遗留代码"堆.
正如我所看到的,您可以在实际中添加到属性的真实值受限于您可以从中获得的值.请查看此处的AttributeSet类引用以获取更多提示.
你可以获得:
getAttributeBooleanValue),getAttributeFloatValue),getAttributeIntValue),getAttributeUnsignedIntValue),getAttributeValue)Rad*_*ing 65
@Aleadam的回答非常有帮助,但是它忽略了enum和之间的一个主要区别flag.前者用于我们选择一个,当我们为某个View分配相应的属性时,只选择一个值.但是,可以使用按位OR运算符组合后者的值.
一个例子,在 res/values/attr.xml
<!-- declare myenum attribute -->
<attr name="myenum">
<enum name="zero" value="0" />
<enum name="one" value="1" />
<enum name="two" value="2" />
<enum name="three" value="3" />
</attr>
<!-- declare myflags attribute -->
<attr name="myflags">
<flag name="one" value="1" />
<flag name="two" value="2" />
<flag name="four" value="4" />
<flag name="eight" value="8" />
</attr>
<!-- declare our custom widget to be styleable by these attributes -->
<declare-styleable name="com.example.MyWidget">
<attr name="myenum" />
<attr name="myflags" />
</declare-styleable>
Run Code Online (Sandbox Code Playgroud)
在res/layout/mylayout.xml我们现在能做
<com.example.MyWidget
myenum="two"
myflags="one|two"
... />
Run Code Online (Sandbox Code Playgroud)
因此,枚举选择其中一个可能的值,而标志可以组合.数值应该反映这种差异,通常你会希望序列去0,1,2,3,...枚举(用作数组索引,比如说)和标志去,1,2,4,8,...这样它们可以独立添加或删除,使用按位OR |来组合标志.
我们可以使用不是2的幂的值明确定义"元标志",从而为常见组合引入一种简写.例如,如果我们在myflags声明中包含了这一点
<flag name="three" value="3" />
Run Code Online (Sandbox Code Playgroud)
然后我们可以写myflags="three"出来代替myflags="one|two"完全相同的结果3 == 1|2.
就个人而言,我喜欢永远包括在内
<flag name="none" value="0" /> <!-- or "normal, "regular", and so on -->
<flag name="all" value="15" /> <!-- 15 == 1|2|4|8 -->
Run Code Online (Sandbox Code Playgroud)
这将允许我立即取消设置或设置所有标志.
更巧妙的是,可能是另一个标志暗示了一个标志.因此,在我们的示例中,假设eight设置的标志应强制设置four标志(如果尚未设置).然后我们可以重新定义eight以预先包括four旗帜,
<flag name="eight" value="12" /> <!-- 12 == 8|4 -->
Run Code Online (Sandbox Code Playgroud)
最后,如果要声明库项目中的属性但想要将它们应用于另一个项目的布局(依赖于lib),则需要使用必须在XML根元素中绑定的命名空间前缀.例如,
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:auto="http://schemas.android.com/apk/res-auto"
... >
<com.example.MyWidget
auto:myenum="two"
auto:myflags="one|two"
... />
</RelativeLayout>
Run Code Online (Sandbox Code Playgroud)