在自定义XML资源中引用字符串资源

5
在我的Android应用项目的assets文件夹中,我存储了描述游戏操作的自定义XML文件。由于它们有些复杂,无法直接编写为Android资源。
更新:现在我将自定义(复杂)XML文件存储在res/xml文件夹中。
简单示例:
<dialog>
    <npc>1</npc>
    <text>Hello! How are you?</text>
</dialog>

我希望能够利用Android字符串资源的便利优势进行语言本地化。在上面的示例中,我想将“Hello! How are you?”保存在我的“res/values/strings.xml”文件中,然后以以下方式引用:
<text>@string/dialog_1_text</text>

我不想创建不同的语言 res/xml 文件夹,然后将所有xml文件复制并完全翻译它们。我只想翻译其中的一部分,并通过引用String资源轻松实现。
更新2:我现在已经发现你从Resource.getXml()获得的XMLParser有一个名为getAttributeResourceValue()的方法,它可以自动将属性(如randomAtt="@string/random_string")转换为实际的Resource ID。 然而,在XML文件中,仍然没有明确的依赖性,也没有字符串的预览或警告,当你输入无效的资源时。但是 - 既然有这样的方法 - 我强烈相信可以让验证器只允许在一些自定义属性中使用字符串资源。

如果它有本地化字符串,为什么要将其存储为资产?最好将它们存储在资源下的xml目录中,而不是资产。 - greenrobo
2
因为资源文件夹中的所有XML文件都需要遵循特定的Android结构。而对于某些任务,我需要使用自己的模式创建更复杂的XML文件。这在“res”中是不允许的。 - Tobias Baumeister
1
根据Android文档,您可以在资源下创建一个名为“xml”的目录,并在其中存储任意的XML文件。您是否探索过这个选项?在使用这种方法时,您遇到了任何限制吗? - greenrobo
1
啊,哇,我怎么没注意到那个!谢谢!...不过问题仍然存在:现在我该如何从内部引用一个字符串呢?我尝试在自定义的“text”标签中输入@string/,但没有自动完成,所以我认为它是不可引用的。 - Tobias Baumeister
我更新了第一篇帖子,感谢@greenrobo。然而,我仍然不知道如何在自定义XML资源文件中引用字符串资源。 - Tobias Baumeister
1个回答

10

好的,在过去两个小时里进行了大量的研究之后,我终于找到了一个非常有效的解决方案。我看到了一些类似问题的讨论帖子,所以我相信这个答案可能会帮助未来的一些程序员。

要求:
我的任务要求是:在自己的模式下引用字符串资源在自定义XML文件中,存储在res/xml目录中。 Android Studio的XML验证器应该自动将其检测为一个字符串资源,并在其无效时打印警告-并在其为有效资源时预览实际字符串。同时它也应尽可能高效。

解决方法:
这就是我的解决方法:
不是把字符串资源放在标签之间,而是作为属性放置。在我的情况下并没有什么大不了的问题。
为了使验证器识别它们为字符串资源,我必须从android命名空间调用这些属性text 更新: 我发现你可以随意称呼属性名称,并且不需要包括android命名空间。

<main>
    <nested>
        <test myText="@string/lorem_ipsum_100"/>
    </nested>
</main>

您的自定义XML可以看起来像您想要/需要的任何样子!这只是一个示例——它可以使用无限嵌套的标记和您自己定义的模式。

我本来不认为这会起作用,但实际上它效果相当好!每当我点击构建项目时,如果我使用了无效的字符串资源,它就会打印出警告。
而且不仅如此,它还会按预期进行预览: String preview in Android Studio

(注意:此截图是在我注意到您可以根据需要调用属性之前创建的。没有必要明确调用 android:text 。只要您放置@string/...,Android Studio将自动识别它为字符串资源。)

最后但并非最不重要的是,要让您的Java代码正确解释资源,您必须执行以下操作:

XmlResourceParser parser = getResources().getXml(R.xml.tutorial_welcome_dialog);
try {
    while (parser.next() != XmlPullParser.END_DOCUMENT) {
        if (parser.getEventType() == XmlPullParser.START_TAG && parser.getName().equals("test")) {
            String s;
            for (int i = 0; i < parser.getAttributeCount(); i++) {
                if (parser.getAttributeName(i).equals("text"))
                    s = getResources().getString(parser.getAttributeResourceValue(i, -1));
            }
        }

    }
} catch (Exception e) {
    e.printStackTrace();
}

性能注意: 就我所看到的,由于Android会自动将@string/...预解析为资源ID,因此此解决方案也非常高效。


有没有办法让 Android 在两个 XML 标签之间的引用也在不在属性值中时进行预解析? - Nicolas

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