0

在 Android 应用程序中,我需要从当前选择的资源文件夹之外的资源文件夹中选择资源(界面语言是系统选择的任何语言,但用户可以为 TTS 选择不同的语言)。由于应用程序的结构方式,切换资源不是一种选择;我同时需要默认设置和备用设置。例如,当用户界面为英语时,我可以使用此代码选择西班牙语字符串:

class SpanishStrings()
{
    private Resources mResources;

    public Foo(Context context)
    {
        final Resources oldResources = context.getResources();
        Configuration oldConfiguration = oldResources.getConfiguration();
        DisplayMetrics metrics = oldResources.getDisplayMetrics();
        Configuration configuration = new Configuration(oldConfiguration);
        configuration.locale = new Locale("es", "es");
        mResources = new Resources(oldResources.getAssets(), metrics, configuration);
    }

    String getString(int id)
    {
        return mResources.getString(id);
    }
}

但这也将整个用户界面设置为西班牙语!Android 一次只能有一个活动资源吗?

这是在 Android 2.3.4 上运行的,如果这有什么不同的话。

4

2 回答 2

2

我找到了一种让它工作的方法。给定问题中的类,删除构造函数并像这样更改 getString() :

String getString(int id)
    {
        final Resources oldResources = mContext.getResources();
        final Configuration oldConfiguration = oldResources.getConfiguration();
        final DisplayMetrics metrics = oldResources.getDisplayMetrics();
        final Configuration configuration = new Configuration(oldConfiguration);
        configuration.locale = new Locale("es", "es");
        Resources resources = new Resources(oldResources.getAssets(), metrics, configuration);
        final String result = resources.getString(id);
        oldResources.updateConfiguration(oldConfiguration, metrics);
        return result;
    }

重要的是 updateConfiguration。我查看了 android.content.res.Resources 的代码,结果发现 Resources() 构造函数调用了 updateConfiguration(),而 updateConfiguration() 调用了 mAssets.setConfiguration()。这意味着对配置的任何更改都将应用于同一 AssetManager 实例的所有用户。

我没有比这更深入,我知道可以通过保留两组资源并仅调用 updateConfiguration() 而不是在检索字符串之前和之后构造一个全新的 Resources 对象来优化上述答案,所以如果有人知道如何创建一个全新的 AssetManager() 实例然后请发布比这更好的答案!

编辑:在我当前的代码中,我通过子类化资源减少了使用的痛苦,如下所示:

final oldResources = context.getResources();
final Configuration configuration = new Configuration(mDefaultResources.getConfiguration());
configuration.locale = new Locale("es", "es");
mResources = new Resources(mDefaultResources.getAssets(), mDefaultResources.getDisplayMetrics(), configuration)
    {
        @Override
        public String getString(int id) throws NotFoundException
        {
            updateConfiguration(getConfiguration(), getDisplayMetrics());
            String result = super.getString(id);
            oldResources.updateConfiguration(oldResources.getConfiguration(), oldResources.getDisplayMetrics());
            return result;
        }
    };
于 2013-07-11T23:19:36.240 回答
0

尝试像这样修改您的代码(取自https://stackoverflow.com/a/10879185/446963

 cMK = getResources().getStringArray(R.array.cities);
 Configuration confTmp =new Configuration( getResources().getConfiguration());
 confTmp.locale = new Locale("en");
 DisplayMetrics metrics = new DisplayMetrics();
 getWindowManager().getDefaultDisplay().getMetrics(metrics);
 Resources resources = new Resources(getAssets(), metrics, confTmp);
 /* get localized string */
 cENG = getResources().getStringArray(R.array.cities);

在您的代码中,您是从原始资源到新资源的指标和资产。所以我认为新资源中的这些对象发生的任何变化并过滤回原始资源。

使用上面的代码为所有需要的资源参数创建新对象。只是一个猜测,但看看它是否有效......

于 2013-07-11T22:42:00.423 回答