styles.xml中的自定义属性

188

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

我在styles.xml中的所有标记中,包括<?xml><resources><style>中都加入了xmlns:custom="http://schemas.android.com/apk/res/com.my.package",但仍然出现相同的错误,无法找到我的自定义XML命名空间。

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


1
cutsom:xmlns=...?难道不应该是 xmlns:cutsom=... 吗? - Selvin
是的,这就是我没有使用复制/粘贴的结果,谢谢。 - Tyler
6个回答

369

我明白了!答案是在样式中不要指定命名空间。

<?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>

13
错误消失了,但是我的视图没有采用属性值,而它采用了其他(非自定义)属性。我的特定属性是一个枚举。以上代码片段是否对你起作用? - Paul Lammertsma
3
使用API 16,这段代码在我的电脑上甚至无法编译。 - David Miler
这种方式对我可用,使用API Level 17。我尝试删除xmlns:custom命名空间声明,它仍然可以工作,我在下面的答案中描述。 - VinceStyling
3
虽然这个方法可行,但如果同名属性存在于两个或更多的包中但包名不同,解析属性时可能会出现问题。 - Johann
@NickSpacek 看起来它已经被编辑为更高版本的SDK和/或Android Studio。我当时是在Eclipse中编写的。 - Tyler
显示剩余3条评论

44

之前的回答对我有用,我稍微修改了一下。我在资源元素中为一个类声明了styleable。

<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>

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


20

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_width="wrap_content"
    android:layout_height="?attr/defaultButtonHeight"
    android:text="Button"
    android:textColor="?attr/defaultButtonColor"
    />

输入图像描述

演示


10

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

为了测试假设,即 declare-styleable 的 name 属性与自定义视图类的名称匹配使我们能够访问自定义属性而不需要命名空间,我更改了 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 命名空间中的属性,你只需要指定属性名称。 - pr-shadoko

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>

试一下,祝你有美好的一天,这对我有效。


2

如果有人需要的话,我的错误在于我的自定义视图类调用了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(而不是通过样式)传递自定义属性时,我花了一段时间才注意到我的代码与其他示例之间的这个关键差异。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接