Android:如何使用资源名称从资源中获取字符串?


553

我想为UI提供2种语言,并在我的资源文件中为它们提供单独的字符串值res\values\strings.xml

<string name="tab_Books_en">Books</string>
<string name="tab_Quotes_en">Quotes</string>
<string name="tab_Questions_en">Questions</string>
<string name="tab_Notes_en">Notes</string>
<string name="tab_Bookmarks_en">Bookmarks</string>

<string name="tab_Books_ru">Книги</string>
<string name="tab_Quotes_ru">Цитаты</string>
<string name="tab_Questions_ru">Вопросы</string>
<string name="tab_Notes_ru">Заметки</string>
<string name="tab_Bookmarks_ru">Закладки</string>

现在,我需要在应用程序中动态检索这些值:

spec.setContent(R.id.tabPage1);
String pack = getPackageName();
String id = "tab_Books_" + Central.lang;
int i = Central.Res.getIdentifier(id, "string", pack);
String str = Central.Res.getString(i);

我的问题是i = 0

为什么在我的情况下不起作用?


1
您确定Central.lang是en还是ru吗?
K-ballo

1
需要更多信息来检查您的代码。得到我之前每个var的状态是什么?无论如何,您应该使用Android中的默认本地化支持来简化操作。
Alin

Answers:


1069

您引用的链接似乎可以在运行时生成的字符串中使用。strings.xml中的字符串不是在运行时创建的。你可以通过

String mystring = getResources().getString(R.string.mystring);

getResources()Context该类的一种方法。如果您位于Activity或中Service(扩展了Context),则可以在此代码段中使用它。

还要注意,整个语言依赖性可以由android框架处理。只需为每种语言创建不同的文件夹。如果英语是您的默认语言,只需将英语字符串放入中res/values/strings.xml。然后创建一个新文件夹values-ru,并将名称相同的俄语字符串放入res/values-ru/strings.xml。从这一点开始,android会在您调用getString()或通过引用XML中的字符串时,根据设备的语言环境为您选择正确的字符串@string/mystring。来自的res/values/strings.xml是后备的,如果您没有覆盖用户区域设置的文件夹,则该文件夹将用作默认值。

有关更多信息,请参见本地化提供资源


23
如果您位于android.support.v4.app.Fragment,则可以直接致电getString(R.string.mystring)
JaKXz 2014年

3
我只是在哭。为什么这样做(由Google完成)这么复杂?首先获取mystring的数字ID(从R对象),然后通过该ID获取字符串?而“ ID-of-mystring => ActualValue”对实际位于何处?据我所知,mystring =>
my

2
确保“R”是项目的R值不要默认的Android R.
ralphgabb

2
这可能是需要的答案,但这不是要求的答案!有关通过名称动态访问字符串资源的信息,请参见@leonvian ...的答案,这应该是公认的IMO
克里斯·哈顿

321

我也有同样的问题。但是下面的代码对我有用:验证您的packageName是否正确。您必须参考Android应用程序的根软件包。

private String getStringResourceByName(String aString) {
      String packageName = getPackageName();
      int resId = getResources().getIdentifier(aString, "string", packageName);
      return getString(resId);
    }

9
如果有人有充分的理由这样做(例如,数据文件包含一个自定义字符串,该字符串决定应显示哪个资源字符串,或者该字符串是从Internet提取的),那么我想指出一点此解决方案是正确的。在资源型特别纠正部分string,而不是strings。因为这是合乎逻辑的(就像其他Android设备一样)。因此,感谢(还有更多)@leonvian。:-)
IvanVučica13年

2
@Sameer通过字符串获取数组只需使用:res.getStringArray(R.array.planets_array); 看一下这个官方链接:developer.android.com/guide/topics/resources/…–
leonvian

3
凉。要摆脱单独的方法声明,可以通过以下方式“简化”:String someStringFromXML = getString(getResources().getIdentifier("some_string_name", "string", getPackageName()));
神经递质

80

不仅来自活动:

    public static String getStringByIdName(Context context, String idName) {
        Resources res = context.getResources();
        return res.getString(res.getIdentifier(idName, "string", context.getPackageName()));
    }

非常有效,谢谢
Mosa

39
getResources().getString(getResources().getIdentifier("propertyName", "string", getPackageName()))

26

我会在leonvian的解决方案中添加一些内容,因此,如果在资源中找不到该字符串(返回值0,这不是有效的资源代码),该函数可能会返回以下内容:

private String getStringResourceByName(String aString) {
    String packageName = getPackageName();
    int resId = getResources()
            .getIdentifier(aString, "string", packageName);
    if (resId == 0) {
        return aString;
    } else {
        return getString(resId);
    }
}

15

最佳方法

App.getRes().getString(R.string.some_id)

可以在所有地方使用(实用程序,模型也可以)。

我已经阅读了所有答案,所有答案都可以使您的工作做好。

  • 您可以使用getString(R.string.some_string_id)两种ActivityFragment
  • 您可以Context.getString(R.string.some_string_id)在没有直接访问getString()方法的地方使用。喜欢Dialog

问题

您没有Context访问权限时,就像您的Util类中的方法一样。

假设下面的方法没有上下文。

public void someMethod(){
    ...
    // can't use getResource() or getString() without Context.
}

现在,您将Context在此方法中作为参数传递并使用getString().

public void someMethod(Context context){
    ...
    context.getString(R.string.some_id);
}

我所做的是

public void someMethod(){
    ...
    App.getAppResources().getString(R.string.some_id)
}

什么?在您的应用程序中的任何地方使用非常简单!

因此,这里是一个解决方案,您可以通过它从任何地方访问资源Util class

import android.app.Application;
import android.content.res.Resources;

public class App extends Application {
    private static Resources resources;

    @Override
    public void onCreate() {
        super.onCreate();

        resources = getResources();
    }

    public static Resources getAppResources() {
        return resources;
    }

}

将名称字段添加到manifest.xml <application标签。

<application
        android:name=".App"
        ...
        >
        ...
    </application>

现在你很好。App.getAppResources().getString(R.string.some_id)在应用程序中的任何地方使用。


+1简单干净的解决方案。请注意拼写错误getResourses,这getResources会导致覆盖。同样,单例模式似乎不必要,可能会被跳过。此解决方案是否存在内存泄漏问题?
Xarvalus

@Xarvalus这会导致内存泄漏吗?
Khemraj

在我的应用程序中都很好:)只是想知道是否有人对此有任何问题。如果遇到任何陷阱,我将通知您。
Xarvalus

1
@Xarvalus内存泄漏通常发生在使用变量的地方,即使父类被破坏也是如此。就像在“活动,片段”中一样。我认为这种情况不会发生。
Khemraj


14

一种将资源字符串从字符串转换为TextView的简单方法。这里resourceName是资源的名称

int resID = getResources().getIdentifier(resourceName, "string", getPackageName());
textview.setText(resID);

7

如果没有活动参考,则可以通过以下方式使用上下文:

getContext().getString(R.string.your_string_name);

4

还有一组预定义的Android字符串,例如“ Ok”,“ Cancel”和许多其他字符串 -因此您不必全部声明。可以通过以下方式简单地获得它们:

getString(android.R.string.ok)

(在这种情况下,为“ Ok”字符串)。顺便说一句,还有其他可用的Android资源,例如图标图像等。



1

您可以在活动中尝试:

getResources().getString(R.string.your string name);

在其他情况下,例如碎片,...使用

getContext().getResources().getString(R.string.your string name);

0

为了安全起见,您应该添加:mContext.getResources()。getString(R.string.your_string);

mContext可以是:Fragment的onAttach()或Activity的上下文。


0

如果您希望将其放入活动或fragmnet中,则:

getContext().getResources().getString(R.string.string_name);

如果要从没有活动上下文的活动或片段之外的类中获取它,请使用应用程序上下文:

getApplicationContext().getResources().getString(R.string.string_name);

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.