Android库项目使用declare-styleable -- 如何编译?

14

我有一个自定义的首选项控件,我在values/attrs.xml中定义了一些属性。为了聚焦讨论,这里是一个在values/attrs.xml中可能找到的属性示例:

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <declare-styleable name="MyCustomView">
        <attr name="android:text"/>
        <attr name="android:textColor"/>            
        <attr name="extraInformation" format="string" />
    </declare-styleable>
</resources>

要使用属性,您需要在希望使用它的位置使用xmlns标签,它看起来像这样:

xmlns:custom="http://schemas.android.com/apk/res/com.conundrum.app.lib"

问题在于:xmlns定义引用了LIBRARY的包名,在LIBRARY项目中,此资源可以编译通过。但是,包含Library项目的Android项目具有不同的包名,并且Android试图合并所有资源。当它到达这个xmlns定义时,它会停止,因为在包含的Android项目中包名不同。

有没有人有关于如何在Library项目中使用xmlns引用以在包含的Android项目中仍然有效的想法?

当Android考虑库时,declare-styleables是否只是Android团队的疏忽?


如果lib包在app包中,即app包为“com.conundrum.app”,而lib类在“com.conundrum.app.lib”中,它是否有效?另外,您是否尝试在布局文件中使用完整的类名标签,而不是前缀? - manmal
我的包名目前就像你建议的那样。问题在于,你实际上不能使用完整的类名,因为这个包是根据构建者的视角不同而不同(无论你当前是在库项目还是Android项目中)。同时,在这种情况下,我正在一个首选项文件中使用xmlns引用,而不是布局。 - Jonathan Schneider
6个回答

9

我曾经在styleable和库方面做了很多实践,以下是我的观察:

想象你有一个包含主项目和子库的项目:

main
   |--- library
  • 即使库中包含可样式化的内容,编译包含库的应用程序也没有问题。例如,您可以包含我的其中一个库(http://code.google.com/p/tree-view-list-android/)。您会发现许多可样式化属性(如可折叠)和一些在库中使用它的XML。所有这些都可以编译并正常工作,无论是单独编译库还是作为包含库...所以这里看起来很好.....
  • 现在,当您在库和主项目中都有相同名称的资源时,您可能会遇到编译主项目的奇怪问题。我最初不理解它,但现在我知道它是如何工作的。例如,如果您的库中有一个具有android:id="@+id/some_id"的main.xml,然后在您的主项目中又有另一个main.xml(没有some_id id),那么R.id.some_id将在编译库时生成,但不会在主项目中生成-这可能会导致主项目编译错误,因为包含的库.java文件很可能会使用R.id.some_id(将丢失)。我最初误解了问题,并尝试动态获取id,但最终不需要-只需确保库中的布局xml使用某种私有命名空间即可。
  • 现在最有趣的部分-如何在项目的layout.xml中引用可样式化参数?正如您注意到的那样,以下内容将不起作用:xmlns:custom="http://schemas.android.com/apk/res/YOUR_LIBRARY_PACKAGE" 令人惊讶的是,以下内容可以工作:xmlns:custom="http://schemas.android.com/apk/res/YOUR_MAIN_APP_PACKAGE"(!) 这似乎确实是Android团队的疏忽,但一旦您知道它,它就可以无缝地工作。

Jarek,你离问题很近了。我确实可以在主应用中使用xmlns声明并引用库中的可引用样式属性。但是如果库本身具有需要引用可引用样式属性的常见首选项文件或布局怎么办呢?在这种情况下,在库中必须使用库包名称,但是当此首选项或布局合并到主项目中时,它不再编译。似乎没有其他方法可以解决这个问题,除非复制任何具有对可引用样式属性的引用的公共布局或首选项文件。 - Jonathan Schneider
在我的库中,我并没有遇到这个问题。当我使用library-package-xmlns引用attrs时,我的库实际上是可以编译的。只有在我描述的情况下(当ids被引用到在主项目中“隐藏”的布局中)才无法编译。你可以自己尝试一下,在你的项目中使用我的库,即使main_demo.xml布局引用了“collapsible”属性,它也应该能正确编译。 - Jarek Potiuk

6

使用http://schemas.android.com/apk/res-auto

我在AndroidSVG项目中偶然发现了这个解决方案:

注意命名空间中特殊的模式URL。如果您使用自己项目中的自定义视图,则应使用基于您包名称的URL。例如,http://schemas.android.com/apk/res/com.example.customview。但是,由于自定义视图位于已包含的库中,因此您应该使用res-auto快捷方式。真实的架构URL将在构建您的应用时自动插入。

(我在上面引用的文本中修正了一个错别字 - 缺少/res/子文件夹)


5

这是Android中的一个已知问题。预计在开发工具的下一个版本(r13)中会进行修复。


在错误报告中的简短回答是,现在您可以使用: http://schemas.android.com/apk/res-auto而不是任何其他命名空间URI,它可以正常工作。 - Damon Smith

3
我也遇到了同样的问题。我的应用程序无法检测到库项目中的styleable xml。
我尝试了以下操作:
我的库项目包名:com.lib.mylibrary 我的应用程序项目包名:com.app.myapp 我尝试使用xmlns:custom="http://schemas.android.com/apk/res/com.app.myapp代替xmlns:custom="http://schemas.android.com/apk/res/com.lib.mylib
这样就可以正常工作了,即:
xmlns:custom="http://schemas.android.com/apk/res/<your app package>

替代

xmlns:custom="http://schemas.android.com/apk/res/<your lib project package>

我从这里得到了这个想法。

1

可能有点晚了,但是这个问题似乎在最新的(r14)开发工具版本中已经修复了。


0

这个对我起作用了。我还记得在Xamarin中遇到过这个问题,同样的解决方案也适用于Xamarin。

xmlns:ab="http://schemas.android.com/apk/res-auto"


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