从strings.xml中的另一个字符串引用一个字符串?

dbm*_*dbm 215 xml string android

我想在strings.xml文件中引用另一个字符串中的字符串,如下所示(特别注意"message_text"字符串内容的结尾):

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <string name="button_text">Add item</string>
    <string name="message_text">You don't have any items yet! Add one by pressing the \'@string/button_text\' button.</string>
</resources>
Run Code Online (Sandbox Code Playgroud)

我已经尝试了上面的语法,然后文本打印出"@ string/button_text"作为明文.不是我想要的.我想要打印消息文本"你还没有任何项目!按"添加项目"按钮添加一个项目."

有没有任何已知的方法来实现我想要的?

RATIONALE:
我的应用程序有一个项目列表,但是当该列表为空时,我会显示"@android:id/empty"TextView.TextView中的文本是通知用户如何添加新项目.我想让我的布局变得傻瓜变化(是的,我是个傻瓜:-)

Bee*_* Jk 218

在不使用Java代码的情况下在xml中插入常用字符串(例如app name)的好方法: source

    <?xml version="1.0" encoding="utf-8"?>
    <!DOCTYPE resources [
      <!ENTITY appname "MyAppName">
      <!ENTITY author "MrGreen">
    ]>

<resources>
    <string name="app_name">&appname;</string>
    <string name="description">The &appname; app was created by &author;</string>
</resources>
Run Code Online (Sandbox Code Playgroud)

更新:

你甚至可以定义你的实体全球,例如:

RES /生/ entities.ent:

<!ENTITY appname "MyAppName">
<!ENTITY author "MrGreen">
Run Code Online (Sandbox Code Playgroud)

RES /值/ string.xml:

<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE resources [
    <!ENTITY % ents SYSTEM "./res/raw/entities.ent">
    %ents;   
]>

<resources>
    <string name="app_name">&appname;</string>
    <string name="description">The &appname; app was created by &author;</string>
</resources>
Run Code Online (Sandbox Code Playgroud)

  • 这是对OP的正确答案.此解决方案还有其他很多好处:**(1)**您可以在外部文件中定义DTD并从任何资源文件引用它以在您的资源中的任何位置应用替换.**(2)**android studio允许你重命名/引用/重构定义的实体.但是,它在写入时不会自动完成名称.(androidstudio 2.2.2) (8认同)
  • Android Studio不再支持外部实体,因为此处讨论的错误:/sf/answers/3593166741/ (7认同)
  • 如果您在Android库项目中使用它,请小心 - 您无法在应用中覆盖它. (5认同)
  • 是否可以在gradle文件中定义flavor时更改实体值? (4认同)
  • @RJFares你可以走两种方式:**(a)**"包括"一个完整的实体文件EG:看看[这个答案](http://stackoverflow.com/a/31346100/4170781).或**(b)**:包括外部DTD中定义的每个实体,如[here]所示(http://www.w3schools.com/xml/xml_dtd_entities.asp).请注意,任何一个都不是完美的,因为(a)你将失去"重构"的能力,(b)非常冗长 (3认同)
  • @MauroPanzeri没有设法引用外部实体文件.你介意发表一个例子吗?谢谢. (2认同)
  • 即使我得到相同的错误`某事'被引用,但没有声明.有谁发现任何解决方案 (2认同)
  • 同样的问题:引用了实体"appname",但没有声明. (2认同)

Bar*_*man 173

只要整个字符串包含引用名称,就可以引用另一个.例如,这将工作:

<string name="app_name">My App</string>
<string name="activity_title">@string/app_name</string>
<string name="message_title">@string/app_name</string>
Run Code Online (Sandbox Code Playgroud)

它对于设置默认值更有用:

<string name="string1">String 1</string>
<string name="string2">String 2</string>
<string name="string3">String 3</string>
<string name="string_default">@string/string1</string>
Run Code Online (Sandbox Code Playgroud)

现在,您可以string_default在代码中的任何位置使用,您可以随时轻松更改默认值.

  • 这不应该是"只要你引用整个字符串"(你总是按照定义),但"只要引用的字符串资源只包含引用名称". (50认同)
  • 这不是一个真正的引用,这只是一个别名,它不能解决组成字符串的问题. (50认同)
  • 这几乎没有用,我想不出任何有用的情况。只需引用实际字符串而不是“别名” (4认同)
  • 这不能回答问题,他们希望将一个字符串嵌入另一个字符串。 (2认同)

Fra*_*ita 92

我想你不能.但您可以根据需要"格式化"字符串:

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <string name="button_text">Add item</string>
    <string name="message_text">You don't have any items yet! Add one by pressing the %1$s button.</string>
</resources>
Run Code Online (Sandbox Code Playgroud)

在代码中:

Resources res = getResources();
String text = String.format(res.getString(R.string.message_text),
                            res.getString(R.string.button_text));
Run Code Online (Sandbox Code Playgroud)

  • `String text = res.getString(R.string.message_text,res.getString(R.string.button_text));`有点清洁. (34认同)
  • 我实际上希望有一个"非逻辑"的解决方案.然而,一个公平的答案(和它的纯粹速度给你一个绿色的复选标记:-) (5认同)

May*_*hta 32

在Android中,你无法在xml中连接字符串

不支持以下内容

<string name="string_default">@string/string1 TEST</string>
Run Code Online (Sandbox Code Playgroud)

请查看下面的链接,了解如何实现它

如何在android XML中连接多个字符串?

  • 好吧,有趣的故事:这是我对你引用的类似问题的回答:-) (13认同)

Val*_*kov 13

我创建了简单的gradle 插件,允许您从另一个字符串中引用一个字符串.您可以引用在另一个文件中定义的字符串,例如在不同的构建变体或库中.这种方法的缺点 - IDE重构不会找到这样的引用.

使用{{string_name}}语法来引用字符串:

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <string name="super">Super</string>
    <string name="app_name">My {{super}} App</string>
    <string name="app_description">Name of my application is: {{app_name}}</string>
</resources>
Run Code Online (Sandbox Code Playgroud)

要集成插件,只需将下一个代码添加到您的应用程序或库模块级build.gradle文件中

buildscript {
  repositories {
    maven {
      url "https://plugins.gradle.org/m2/"
    }
  }
  dependencies {
    classpath "gradle.plugin.android-text-resolver:buildSrc:1.2.0"
  }
}

apply plugin: "com.icesmith.androidtextresolver"
Run Code Online (Sandbox Code Playgroud)

更新: 该库不适用于Android gradle插件版本3.0及更高版本,因为新版本的插件使用aapt2将资源打包成.flat二进制格式,因此打包资源不可用于库.作为临时解决方案,您可以通过在gradle.properties文件中设置android.enableAapt2 = false来禁用aapt2.

  • 我创建了一个插件,它的功能几乎相同并且可以与 aapt2 一起使用:https://github.com/LikeTheSalad/android-string-reference :) (3认同)

sch*_*rer 7

您可以使用自己的逻辑,以递归方式解析嵌套字符串.

/**
 * Regex that matches a resource string such as <code>@string/a-b_c1</code>.
 */
private static final String REGEX_RESOURCE_STRING = "@string/([A-Za-z0-9-_]*)";

/** Name of the resource type "string" as in <code>@string/...</code> */
private static final String DEF_TYPE_STRING = "string";

/**
 * Recursively replaces resources such as <code>@string/abc</code> with
 * their localized values from the app's resource strings (e.g.
 * <code>strings.xml</code>) within a <code>source</code> string.
 * 
 * Also works recursively, that is, when a resource contains another
 * resource that contains another resource, etc.
 * 
 * @param source
 * @return <code>source</code> with replaced resources (if they exist)
 */
public static String replaceResourceStrings(Context context, String source) {
    // Recursively resolve strings
    Pattern p = Pattern.compile(REGEX_RESOURCE_STRING);
    Matcher m = p.matcher(source);
    StringBuffer sb = new StringBuffer();
    while (m.find()) {
        String stringFromResources = getStringByName(context, m.group(1));
        if (stringFromResources == null) {
            Log.w(Constants.LOG,
                    "No String resource found for ID \"" + m.group(1)
                            + "\" while inserting resources");
            /*
             * No need to try to load from defaults, android is trying that
             * for us. If we're here, the resource does not exist. Just
             * return its ID.
             */
            stringFromResources = m.group(1);
        }
        m.appendReplacement(sb, // Recurse
                replaceResourceStrings(context, stringFromResources));
    }
    m.appendTail(sb);
    return sb.toString();
}

/**
 * Returns the string value of a string resource (e.g. defined in
 * <code>values.xml</code>).
 * 
 * @param name
 * @return the value of the string resource or <code>null</code> if no
 *         resource found for id
 */
public static String getStringByName(Context context, String name) {
    int resourceId = getResourceId(context, DEF_TYPE_STRING, name);
    if (resourceId != 0) {
        return context.getString(resourceId);
    } else {
        return null;
    }
}

/**
 * Finds the numeric id of a string resource (e.g. defined in
 * <code>values.xml</code>).
 * 
 * @param defType
 *            Optional default resource type to find, if "type/" is not
 *            included in the name. Can be null to require an explicit type.
 * 
 * @param name
 *            the name of the desired resource
 * @return the associated resource identifier. Returns 0 if no such resource
 *         was found. (0 is not a valid resource ID.)
 */
private static int getResourceId(Context context, String defType,
        String name) {
    return context.getResources().getIdentifier(name, defType,
            context.getPackageName());
}
Run Code Online (Sandbox Code Playgroud)

Activity,例如,把它像这样

replaceResourceStrings(this, getString(R.string.message_text));
Run Code Online (Sandbox Code Playgroud)


归档时间:

查看次数:

75930 次

最近记录:

6 年,8 月 前