styles.xml 中的自定义属性

Posted

技术标签:

【中文标题】styles.xml 中的自定义属性【英文标题】:Custom attributes in styles.xml 【发布时间】:2011-10-15 05:02:06 【问题描述】:

我创建了一个自定义小部件,并在 layout.xml 中声明它。我还在 attr.xml 中添加了一些自定义属性。但是,当尝试在 styles.xml 中以样式声明这些属性时,它给了我No resource found that matches the given name: attr 'custom:attribute'.

我已将xmlns:custom="http://schemas.android.com/apk/res/com.my.package" 放在styles.xml 中的所有标签中,包括<?xml><resources><style>,但它仍然给我同样的错误,它找不到我的自定义 XML 命名空间。

但是,我可以使用我的命名空间手动为 layout.xml 中的视图分配属性,因此命名空间没有任何问题。我的问题在于让 styles.xml 知道我的 attr.xml。

【问题讨论】:

cutsom:xmlns=... ??不应该是xmlns:cutsom=... 是的,这就是我不使用复制/粘贴而得到的结果,谢谢 【参考方案1】:

我想通了!答案是NOT在样式中指定命名空间。

<?xml version="1.0" encoding="utf-8" ?>
<resources xmlns:android="http://schemas.android.com/apk/res/android">
    <style name="CustomStyle">
        <item name="android:layout_width">wrap_content</item>
        <item name="android:layout_height">wrap_content</item>

        <item name="custom_attr">value</item> <!-- tee hee -->
    </style>
</resources>

【讨论】:

错误消失了,但是我的视图没有采用属性值,而它确实采用了其他(非自定义)属性。我的特殊属性是枚举。上面的 sn-p 对你有用吗? @PaulLammertsma 我正在使用枚举,这似乎对我也不起作用。如果您没有自定义命名空间 xmlns 属性,您实际上可以为项目名称属性输入您喜欢的任何值,它会编译。 @DavidCaunt 我最终得到了what I was working on 的功能。我最终为declare-stylable 使用了一个字符串,而不是枚举。我不确定为什么枚举不起作用,但这种解决方法对我来说已经足够了。 这甚至不能为我编译,使用 API lvl 16。 虽然这可行,但我怀疑如果两个或多个包中存在具有相同名称但具有不同包名的属性,则解析属性会出现问题。【参考方案2】:

上面的答案对我有用,我尝试了一点改变,我在资源元素中声明了一个类的样式。

<declare-styleable name="VerticalView">
    <attr name="textSize" format="dimension" />
    <attr name="textColor" format="color" />
    <attr name="textBold" format="boolean" />
</declare-styleable>

declare-styleable中,name属性引用了一个类名,所以我有一个视图类调用“com.my.package.name.VerticalView”,它表示此声明必须在 VerticalView 或 VerticalView 的子类中使用。所以我们可以像这样声明样式:

<resources>
    <style name="verticalViewStyle">
        <item name="android:layout_width">match_parent</item>
        <item name="android:layout_height">36dip</item>

        <item name="textSize">28sp</item>  <!-- not namespace prefix -->
        <item name="textColor">#ff666666</item>
        <item name="textBold">true</item>
    </style>
</resources>

这就是为什么我们没有在资源元素中声明命名空间,它仍然有效。

【讨论】:

【参考方案3】:

values/styles.xml

<style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
    ...
    <item name="defaultButtonColor">@color/red</item>
    <item name="defaultButtonHeight">@dimen/dp_100</item>
</style>

values/attrs.xml

<resources>
    <attr name="defaultButtonColor" format="reference" />
    <attr name="defaultButtonHeight" format="reference"/>
</resources>

values/colors.xml

<resources>
    <color name="red">#f00</color>
</resources>

values/dimens.xml

<resources>
    <dimen name="dp_100">100dp</dimen>
</resources>

使用

<Button
    android:layout_
    android:layout_
    android:text="Button"
    android:textColor="?attr/defaultButtonColor"
    />

DEMO

【讨论】:

【参考方案4】:

Styler 和 vince 的修改对我有用。我想指出@vince 的解释可能并不完全准确。

为了检验declare-styleable 的名称属性与自定义视图类的名称匹配是否允许我们在没有命名空间的情况下访问自定义属性的假设,我更改了declare-styleable 的名称(自定义视图被命名为TestViewFont:

<declare-styleable name="TextViewFont2">
    <attr name="font" format="integer"/>
</declare-styleable>

然后我更改了自定义视图中的 obtainStyledAttributes 调用以反映这一点:

TypedArray ta = context.getTheme().obtainStyledAttributes(attrs, R.styleable.TextViewFont2, 0, 0);

代码仍在运行。所以我不认为这是对它命名的类的declare-styleable的某种自省。

因此,我相信任何自定义属性都可以用于声明样式,而无需引用命名空间。

不管怎样,谢谢大家的帮助,它解决了我的问题。

【讨论】:

实际上,属性共享同一个命名空间,无论它们是否在declare-styleable 块中声明。 (对不起,我找不到这个的参考页面……)除了来自android命名空间的属性,你应该只指出属性名称。【参考方案5】:

定义一些属性

<declare-styleable name="refreshPullRefreshLayout">
        <attr name="refreshColors" format="reference"/>
        <attr name="refreshColor" format="reference"/>
</declare-styleable>

在布局文件中使用,如

<com.aolphn.PullRefreshLayout
     app:refreshColor="@color/main_green"
     app:refreshColors="@array/refresh_color"/>

终于在样式文件中使用了

样式文件和布局文件的区别是我们不加前缀app:
<style name="refreshStyle">
    <item name="refreshColor">@color/main_green</item>
    <item name="refreshColors">@array/refresh_color</item>
</style>

试试吧,祝你有美好的一天,这对我有用。

【讨论】:

【参考方案6】:

如果它对其他人有帮助,我的错误是我的自定义视图类调用了AttributeSet.getAttributeValue,例如

String fontName = attrs.getAttributeValue("http://schemas.android.com/apk/res-auto", "customFont");

...这导致我的自定义属性没有被我的自定义视图读取。

解决方法是在我的自定义视图中使用obtainStyledAttributes

 TypedArray styleAttrs = context.obtainStyledAttributes(attrs, R.styleable.MyTextViewStyleable);
 String fontName = styleAttrs.getString(R.styleable.MyTextViewStyleable_customFont);

提示这是正常工作的,您可以 Ctrl/Apple + 单击 R.styleable.MyTextViewStyleable_customFont 直接进入 attrs.xml 定义。

我花了一段时间才发现我的代码和其他示例之间的关键区别,因为自定义属性在直接通过布局 XML(而不是通过样式)传入时工作正常。

【讨论】:

以上是关于styles.xml 中的自定义属性的主要内容,如果未能解决你的问题,请参考以下文章

自定义布局,丢失 attrs.xml 中的自定义属性

Rails 中的自定义命名属性

SceneKit 中的自定义动画属性

.NET Core 中的自定义授权属性 [重复]

Revit 模型中的自定义属性(标识数据)翻译错误

Android中的自定义属性attrs