211

我正在编写一些共享一些同名属性的自定义视图。在他们各自的<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属性 formyattr1myattr2in MyView2,但如果这样做,我会在控制台中获得以下错误:

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

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

4

5 回答 5

444

解决方案:简单地从两个视图中提取公共属性,并将它们直接添加为节点的子<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>
于 2010-12-16T20:17:54.580 回答
67

我发布了这个答案,因为上面发布的解决方案在 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 可样式化,然后我们需要继承该父级可样式化。例如,正如我在上面所做的那样:父样式名称 MyView 并将其分别继承给我的其他样式,例如 MyView1 和 MyView2。

于 2015-10-12T09:18:27.497 回答
30

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

但是,还有其他一些事情需要注意(这就是为什么我还要添加一个答案):

  • 常见的样式不需要与视图命名相同的东西。(感谢this answer指出这一点。)
  • 您不需要对父级使用继承。

例子

这是我在最近的一个项目中所做的,该项目有两个共享相同属性的自定义视图。只要自定义视图仍然具有属性名称并且不包含 a 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>

但是,对于大型项目,这可能会变得混乱,并且在单个位置的顶部定义它们可能会更好(如此推荐)。

于 2017-02-18T09:05:03.723 回答
10

谢谢刘易斯我有同样的问题,你的继承解决方案给了我像下面这样做的提示,它工作正常。我只是在上面声明了公共属性,并在没有格式化的情况下再次在样式声明的主体中重写它。我希望它可以帮助某人

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

于 2017-01-04T16:05:55.837 回答
1

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

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

前:

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

后:

<attr name="subtitle"/>

于 2016-08-09T10:25:39.110 回答