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

我想从我的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>

我已经尝试了上面的语法,但然后文本打印出“@string/button_text”作为明文。不是我想要的。我希望消息文本打印“您还没有任何项目!”按‘添加项目’按钮添加一个。”

有什么已知的方法可以达到我想要的吗?

< p > 理由是: < br / > 我的应用程序有一个项目列表,但当该列表为空时,我显示一个“@android:id/空”TextView代替。TextView中的文本通知用户如何添加新项。我想让我的布局万无一失的变化(是的,我是傻瓜在问题:-)

98047 次浏览

我认为你不能。但是你可以根据自己的喜好“格式化”字符串:

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

在代码中:

Resources res = getResources();
String text = String.format(res.getString(R.string.message_text),
res.getString(R.string.button_text));

只要整个字符串由引用名称组成,就可以在另一个字符串中引用一个。例如,这将工作:

<string name="app_name">My App</string>
<string name="activity_title">@string/app_name</string>
<string name="message_title">@string/app_name</string>

它甚至在设置默认值时更有用:

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

现在你可以在代码中的任何地方使用string_default,并且你可以随时轻松地更改默认值。

在Android中,你不能在xml中连接字符串

不支持以下操作

<string name="string_default">@string/string1 TEST</string>

点击下面的链接,了解如何实现它

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

我知道这是一个较老的帖子,但我想分享我为我的一个项目想出的快速而肮脏的解决方案。它只适用于textview,但可以 也可以适应其他小部件。注意,它要求链接用方括号括起来(例如[@string/foo])
public class RefResolvingTextView extends TextView
{
// ...


@Override
public void setText(CharSequence text, BufferType type)
{
final StringBuilder sb = new StringBuilder(text);
final String defPackage = getContext().getApplicationContext().
getPackageName();


int beg;


while((beg = sb.indexOf("[@string/")) != -1)
{
int end = sb.indexOf("]", beg);
String name = sb.substring(beg + 2, end);
int resId = getResources().getIdentifier(name, null, defPackage);
if(resId == 0)
{
throw new IllegalArgumentException(
"Failed to resolve link to @" + name);
}


sb.replace(beg, end + 1, getContext().getString(resId));
}


super.setText(sb, type);
}
}
这种方法的缺点是setText()CharSequence转换为a String,这是一个问题,如果你传递像SpannableString;为我的 项目这不是一个问题,因为我只使用它TextViews,我不需要 从我的Activity访问

你可以使用你自己的逻辑,递归地解析嵌套的字符串。

/**
* 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());
}

例如,从Activity中,像这样调用它

replaceResourceStrings(this, getString(R.string.message_text));
在xml中插入一个经常使用的字符串(例如应用程序名称)而不使用Java代码的好方法: < / p >
    <?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>

更新:

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

res /生/ entities.ent:

<!ENTITY appname "MyAppName">
<!ENTITY author "MrGreen">

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>

我创建了简单的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>

要集成插件,只需将下一个代码添加到应用程序或库模块级别的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"

< >强更新: 该库不支持Android gradle插件3.0及以上版本,因为该插件的新版本使用aapt2,它将资源打包为.flat二进制格式,因此打包的资源对该库不可用。作为临时解决方案,您可以通过设置android禁用aapt2。在gradle中enableAapt2=false。属性文件。< / p >

你可以使用字符串占位符(% s),并在运行时使用java替换它们

<resources>
<string name="button_text">Add item</string>
<string name="message_text">Custom text %s </string>
</resources>

在Java中

String final = String.format(getString(R.string.message_text),getString(R.string.button_text));

然后将它设置到它使用字符串的地方

使用新的数据绑定,您可以在xml中连接并做更多的事情。

例如,如果你有message1和message2,你可以:

android:text="@{@string/message1 + ': ' + @string/message2}"

你甚至可以导入一些文本utils并调用String。格式和朋友。

不幸的是,如果你想在几个地方重用它,它可能会变得混乱,你不希望这段代码到处都是。你不能在一个地方用xml定义它们(我不知道) 因此,你可以创建一个类来封装这些组合:

public final class StringCompositions {
public static final String completeMessage = getString(R.string.message1) + ": " + getString(R.string.message2);
}

然后您可以使用它(您将需要导入带有数据绑定的类)

android:text="@{StringCompositions.completeMessage}"

除了以上Francesco Laurita的回答https://stackoverflow.com/a/39870268/9400836

这似乎是一个编译错误&实体;被引用,但没有声明”,这可以通过引用外部声明来解决

res /生/ entities.ent

<!ENTITY appname "My App Name">

res /价值/ strings.xml

<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE resources [
<!ENTITY appname SYSTEM "/raw/entities.ent">
]>
<resources>
<string name="app_name">&appname;</string>
</resources

虽然它编译和运行,但它有一个空值。也许有人知道怎么解决。我会发表评论,但最低声誉是50。

我已经创建了一个小库,允许您在构建时解析这些占位符,因此您不必添加任何Java/Kotlin代码来实现您想要的结果。

基于你的例子,你必须像这样设置你的字符串:

<?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 ${button_text} button.</string>
</resources>

然后插件将负责生成以下内容:

<!-- Auto generated during compilation -->
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="message_text">You don't have any items yet! Add one by pressing the Add item button.</string>
</resources>

它也适用于本地化和风味字符串,生成的字符串将保持自己更新,每当你改变你的模板或它的值。

更多信息:https://github.com/LikeTheSalad/android-stem