android 以编程方式更改R.string的值

hjzp0vay  于 2022-11-27  发布在  Android
关注(0)|答案(8)|浏览(260)

我已经在strings.xml文件中声明了一个字符串,并在Activity中使用它作为R.string.compose_title.(将其设置为title,即setTitle(R.id.compose_title))。现在,在某些情况下,我想编辑该字符串,然后使用它来设置标题。我该怎么做呢?
另外,我只需要更改一个字符串的值,所以使用本地化为每个情况(根据用户的不同而不同)声明一个新的strings.xml似乎是一个很低效的操作。

oyjwcjzk

oyjwcjzk1#

在这里你必须了解的一件事是,当你提供一个数据作为资源时,它不能在运行时被修改。例如,你在drawable文件夹中的drawable文件不能在运行时被修改。确切地说,“res”文件夹不能被编程修改。
这也适用于Strings.xml,即“Values”文件夹。如果你想要一个在运行时必须修改的字符串,创建一个单独的类,并将你的字符串放在这个类中,在运行时访问。这是我找到的最好的解决方案。

pgky5nke

pgky5nke2#

示例操作方法:

如何?* 通过将一个变量引用更改为其他引用 *
使用方法:

setRColor(pl.mylib.R.class,"endColor",pl.myapp.R.color.startColor);
// override app_name in lib R class  
setRString(pl.mylib.R.class,"app_name",pl.myapp.R.string.app_name);

基本方法:

public static void setRColor(Class rClass, String rFieldName, Object newValue) {
    setR(rClass, "color", rFieldName, newValue);
}

public static void setRString(Class rClass, String rFieldName, Object newValue) {
    setR(rClass, "string", rFieldName, newValue);
}

// AsciiStrings.STRING_DOLAR = "$";
public static void setR(Class rClass, String innerClassName, String rFieldName, Object newValue) {
    setStatic(rClass.getName() + AsciiStrings.STRING_DOLAR  + innerClassName, rFieldName, newValue);
}

助手方法:

public static boolean setStatic(String aClassName, String staticFieldName, Object toSet) {
    try {
        return setStatic(Class.forName(aClassName), staticFieldName, toSet);
    } catch (ClassNotFoundException e) {
        e.printStackTrace();
        return false;
    }
}

public static boolean setStatic(Class<?> aClass, String staticFieldName, Object toSet) {
    try {
        Field declaredField = aClass.getDeclaredField(staticFieldName);
        declaredField.setAccessible(true);
        declaredField.set(null, toSet);
        return true;
    } catch (Exception e) {
        e.printStackTrace();
        return false;
    }
}

@bradenV2我的应用程序支持多种语言,所以我想从strings.xml中提取一个当前正在使用的字符串,并对其进行更改,然后使用该字符串- atuljangra Mar 12 '12 at 22:04
ps上面的解决方案是很好的,例如当你想在已经编译的lib/jar中注入一些数据时。但是如果你想本地化字符串,只需在res下创建文件夹,每个LANG CODE如values-CC,其中cc是lang代码(values-de,values-cs)等
那么你有两个选择:
1.“内置”系统依赖语言选择-基于设备选择的语言
1.通过为配置创建资源-您决定显示语言
就像这样:

configuration = new Configuration(resources.getConfiguration());
configuration.setLocale(targetLocale);
String localized = Context.createConfigurationContext(configuration)
    .getResources()
    .getString(resourceId);

nsc4cvqm

nsc4cvqm3#

我认为您不能以编程方式自定义R类,因为它是由ADT自动生成的。

wqsoz72f

wqsoz72f4#

我遇到过这样的情况,我的strings.xml值中有一个动态部分。我用“替换文本”(类似于%%REPLACEMENT_EMAIL%%)设置strings.xml,当我想以编程方式使用该字符串时,我检索资源的字符串值,并用动态值(例如用户输入的值)替换该替换文本的示例。
老实说,我的应用程序还没有本地化,但我仍然试图遵循最佳实践w.r.t.不硬编码任何字符串。

e0uiprwp

e0uiprwp5#

使用SharedPreferences而不是Java类。如果你决定从外部**(web)获取**值,它会给予你更多的通用性。在运行时填充Java类在离线时可能是无用的。在SharedPreferences的情况下,你必须确保它们只加载一次,在应用程序第一次启动时,然后只通过手动请求更新,因为将使用以前的导入。

myActivity.getSharedPreferences("com.example.imported",0)
.edit()
.putString("The news",getTheNews())
.apply();
9bfwbjaz

9bfwbjaz6#

您可能希望“修改”string.xml,以便在Activity再次需要它时使用新值,例如在屏幕旋转后保留新的动态标题。
首先,你不能修改资源。它已经被编译过了。你不能修改R类(为什么?)它所有的属性都是“final”。
因此,对于上面的示例,您可以使用onSaveInstanceState()和onRestoreInstanceState()来表示要保持显示的属性。

r9f1avp5

r9f1avp57#

据我所知,你不能改变资源值(R类值),而应用程序运行。为什么不尝试存储在共享首选项?我建议你使用共享首选项

bfhwhh0e

bfhwhh0e8#

我使用下面的方法从API中获取键值对,并将其全局存储在HashMap中,如果在HashMap中找不到键值,则在strings.xml文件中查找该键值,这样就达到了动态更改键值的目的。

public String getAppropriateLangText(String key) {
        String value = "";
        try {
            HashMap<String, String> HashMapLanguageData HashMapLanguageData = gv.getHashMapLanguageData();
            value = HashMapLanguageData.get(key);//Fetching the value of key from API
            if (value == null || value.length() == 0) { //If Key value not found, search in strings.xml file
                String packageName = getPackageName();
                int resId = getResources().getIdentifier(key, "string", packageName);
                value = getString(resId);
            }
        } catch (Exception e) {
            value = "";
        }

        return value;
    }

相关问题