attrs.xml中用于自定义视图的同名属性


179

我正在写一些共享一些同名属性的自定义视图。在它们各自的<declare-styleable>部分中,attrs.xml我想对属性使用相同的名称:

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <declare-styleable name="MyView1">
        <attr name="myattr1" format="string" />
        <attr name="myattr2" format="dimension" />
        ...
    </declare-styleable>

    <declare-styleable name="MyView2">
        <attr name="myattr1" format="string" />
        <attr name="myattr2" format="dimension" />
        ...
    </declare-styleable>
</resources>

我在说一个错误myattr1并且myattr2已经定义了。我发现我应该省略和中的format属性,但是如果这样做,我会在控制台中收到以下错误:myattr1myattr2MyView2

[2010-12-13 23:53:11 - MyProject] ERROR: In <declare-styleable> MyView2, unable to find attribute 

有什么办法可以做到这一点,也许是某种命名空间(只是猜测)?

Answers:


401

解决方案:只需从两个视图中提取通用属性,然后将它们直接添加为<resources>节点的子代即可:

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <attr name="myattr1" format="string" />
    <attr name="myattr2" format="dimension" />

    <declare-styleable name="MyView1">
        <attr name="myattr1" />
        <attr name="myattr2" />
        ...
    </declare-styleable>

    <declare-styleable name="MyView2">
        <attr name="myattr1" />
        <attr name="myattr2" />
        ...
    </declare-styleable>
</resources>

11
myattr1字符串输入MyView1和整数输入时会发生什么MyView2
foxx1337

4
我不这样认为,例如,我们可以具有“方向”属性,并且对于某些视图来说,它是“水平” /“垂直”属性,而对于其他“风景” /“人像” /“正方形”属性。从我的角度来看,这是Android中的一个错误(或至少是不一致的行为)(请牢记:1.可样式化的属性始终以prefix = view name开头,并且2.如果为此类视图创建单独的库项目,那么一切都会正常进行)
se.solovyev

4
当我按照这个答案回答时,我得到了 ERROR: In <declare-styleable> com_app_view_widget, unable to find attribute customAttr 所有试图声明的视图。有任何想法吗?
Dapp 2014年

45
@Google:胡扯的设计
Glenn Bech,

6
@ foxx1337只需使用<attr name="myattr1" format="string|integer" />。为我工作。
Mygod

57

我发布此答案是因为上述解决方案在Android Studio中对我而言不起作用。我需要在自定义视图之间共享我的自定义属性,因此我在Android Studio中尝试了上述解决方案,但没有运气。因此,我尝试并尝试了一种方法。希望它可以帮助寻找相同问题的人。

  <?xml version="1.0" encoding="utf-8"?>
    <resources>
    <!-- parent styleable -->
     <declare-styleable name="MyView">
         <attr name="myattr1" format="string" />
         <attr name="myattr2" format="dimension" />
     </declare-styleable>

     <!-- inheriting parent styleable -->
     <!-- also note "myBackgroundColor" belongs to child styleable"MyView1"-->
    <declare-styleable name="MyView1" parent="MyView">
        <attr name="myattr1" />
        <attr name="myattr2" />
        <attr name="myBackgroundColor" format="color"/>
    </declare-styleable>


    <!-- inheriting parent styleable -->
    <!-- same way here "myfonnt" belongs to child styelable "MyView2" -->
    <declare-styleable name="MyView2" parent="MyView">
        <attr name="myattr1" />
        <attr name="myattr2" />
        <attr name="myfont" format="string"/>
        ...
    </declare-styleable>
</resources>

这完全适合我。我们需要使一个Parent可样式化,然后我们需要继承该Parent可样式化。例如,如上所述:父可设置样式名称MyView并将其分别继承给其他可设置样式的名称,例如MyView1和MyView2。


1
这对我有用。我找不到从引用的答案中引用代码中提取的属性的方法。
Nemanja Kovacevic

嗯..那很奇怪..公认的解决方案似乎对我来说效果很好(targetSdkVersion 27)。也许是因为诸如“文本”之类的属性是常见的,并且可能存在于其他attrs.xml中。
阿坝州

我尝试使用的名称极少见,并且可接受的解决方案仍然对我有用。
阿坝(Aba)

我同意第一个评论!无法引用从typedArray提取的attr。因此,您需要定义一个可样式化的父对象
reavcn '19

为此,请不要忘记在父级而不是子级中解决此属性(对于班级MyView2对:R.styleable.MyView2_myattr1错误对:R.styleable.MyView_myattr1
警惕

27

正如Priya Singhal回答的那样,Android Studio要求在其自己的样式名称中定义通用属性名称。他们不再是根本。

但是,还有两点需要注意(这就是为什么我还要添加答案的原因):

  • 通用样式不必与视图命名相同。(感谢此答案指出了这一点。)
  • 您不需要与父级一起使用继承。

这是我在最近的项目中所做的,该项目具有两个共享相同属性的自定义视图。只要自定义视图仍然具有属性的名称并且不包含format,我仍然可以从代码中正常访问它们。

<?xml version="1.0" encoding="utf-8"?>
<resources>

    <!-- common attributes to all custom text based views -->

    <declare-styleable name="TextAttributes">
        <attr name="text" format="string"/>
        <attr name="textSize" format="dimension"/>
        <attr name="textColor" format="color"/>
        <attr name="gravity">
            <flag name="top" value="48" />
            <flag name="center" value="17" />
            <flag name="bottom" value="80" />
        </attr>
    </declare-styleable>

    <!-- custom text views -->

    <declare-styleable name="View1">
        <attr name="text"/>
        <attr name="textSize"/>
        <attr name="textColor"/>
        <attr name="gravity"/>
    </declare-styleable>

    <declare-styleable name="View2">
        <attr name="text"/>
        <attr name="textSize"/>
        <attr name="textColor"/>
        <attr name="gravity"/>
    </declare-styleable>

</resources>

精简的例子

实际上,我什至不需要将属性放在自定义名称下。只要为format至少一个自定义视图定义它们(给它们一个),我就可以在任何地方(不带format)使用它们。因此这也可以工作(并且看起来更干净):

<?xml version="1.0" encoding="utf-8"?>
<resources>

    <declare-styleable name="View1">
        <attr name="text" format="string"/>
        <attr name="textSize" format="dimension"/>
        <attr name="textColor" format="color"/>
        <attr name="gravity">
            <flag name="top" value="48" />
            <flag name="center" value="17" />
            <flag name="bottom" value="80" />
        </attr>
    </declare-styleable>

    <declare-styleable name="View2">
        <attr name="text"/>
        <attr name="textSize"/>
        <attr name="textColor"/>
        <attr name="gravity"/>
    </declare-styleable>

</resources>

对于一个大的项目,不过,这可能会导致混乱,并在一个位置上定义它们可能会更好(如建议在这里)。


继承有什么问题?我有一个自定义的视图层次结构,其关联的可样式设置不能反映这种关系,只能通过命名约定和其中定义的特定项在关联的样式定义中进行推论(请注意,其中一些属于一个可样式化,而另一些属于另一个样式化)。我宁愿使用该parent属性将其明确显示,但没有看到很多文章暗示它的用法。
samis

@samis,我已经有一段时间没有从事此工作了,但是我对使用没什么错parent。我想我只是说这不是必需的。
Suragch

这不是必需的,我只是制作了另一个子类,该子类包裹了一个我不想放入基类的附加属性。我只是使用注释和命名约定来表示分隔。
samis

7

谢谢刘易斯,我遇到了同样的问题,您的继承解决方案为我提供了如下所示的提示,并且效果很好。我只是在上面声明了公共属性,然后再次将其重写为样式声明的正文而不进行格式化。我希望它可以帮助某人

<?xml version="1.0" encoding="utf-8"?>
<resources>
<!-- common attributes -->
     <attr name="myattr1" format="string" />
     <attr name="myattr2" format="dimension" />

 <!-- also note "myBackgroundColor" belongs to child styleable"MyView1"-->
<declare-styleable name="MyView1" >
    <attr name="myattr1" />
    <attr name="myattr2" />
    <attr name="myBackgroundColor" format="color"/>
</declare-styleable>

<!-- same way here "myfonnt" belongs to child styelable "MyView2" -->
<declare-styleable name="MyView2" parent="MyView">
    <attr name="myattr1" />
    <attr name="myattr2" />
    <attr name="myfont" format="string"/>
    ...
</declare-styleable>


1

万一有人尝试了可用的解决方案后仍然遇到此问题,以防万一。我坚持subtitle使用string格式添加属性。

我的解决方案是删除格式。

之前:

<attr name="subtitle" format="string"/>

后:

<attr name="subtitle"/>

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.