从strings.xml中的另一个string引用一个string?
我想从我的strings.xml文件中的另一个string引用一个string,如下所示(特别注意“message_text”string内容的结尾):
<?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>
我已经尝试了上面的语法,但是文本以纯文本的forms打印出“@ string / button_text”。 不是我想要的。 我想要消息文本打印“您还没有任何项目!按'添加项目'button添加一个。
有没有什么已知的方法来实现我想要的?
理由:
我的应用程序有一个项目列表,但是当这个列表是空的时候,我会显示一个“@android:id / empty”的TextView。 该TextView中的文本是通知用户如何添加一个新的项目。 我想让我的布局更改傻瓜(是的,我是个傻瓜:-)
在xml中插入一个经常使用的string(例如应用程序名称)而不使用Java代码的一个好方法: 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>
更新:
你甚至可以定义你的实体globaly例如:
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>
只要整个string由引用名称组成,就可以引用另一个string。 例如,这将工作:
<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
,并且可以随时轻松更改默认值。
我想你不能。 但是你可以像你想的那样“格式化”一个string:
<?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));
在Android中,你不能连接xml中的string
以下不支持
<string name="string_default">@string/string1 TEST</string>
请查看下面的链接,了解如何实现它
如何在android XML中连接多个string?
你可以使用你自己的逻辑,recursion地parsing嵌套的string。
/** * 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 (eg * <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 (eg 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 (eg 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));
我创build了简单的gradle 插件 ,它允许你从另一个string中引用一个string。 您可以引用在另一个文件中定义的string,例如在不同的构build版本或库中。 这种方法的缺点 – IDE重构不会find这样的引用。
使用{{string_name}}
语法来引用一个string:
<?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.1.0" } } apply plugin: "com.icesmith.androidtextresolver"
我知道这是一个较旧的post,但我想分享我为我的一个项目提出的快速的肮脏的解决scheme。 它只适用于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
转换为一个String
,如果你传递一个SpannableString
话,这是个问题。 对于我的项目,这不是一个问题,因为我只用它的TextViews
,我不需要从我的Activity
访问。
使用新的数据绑定,您可以连接并在xml中执行更多操作。
例如,如果你有message1和message2,你可以:
android:text="@{@string/message1 + ': ' + @string/message2}"
你甚至可以导入一些文本使用情况,并调用String.format和朋友。
不幸的是,如果你想在几个地方重复使用它,可能会变得混乱,你不希望这个代码块到处都是。 你不能在一个地方在xml中定义它们(不是我所知道的),所以你可以创build一个封装这些组合的类:
public final class StringCompositions { public static final String completeMessage = getString(R.string.message1) + ": " + getString(R.string.message2); }
那么您可以使用它(您将需要导入与数据绑定的类)
android:text="@{StringCompositions.completeMessage}"
您可以使用string占位符(%s)并在运行时使用javareplace它们
<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));
然后将其设置为使用该string的位置