Is there an Enum string resource lookup pattern for Android?
我有一个枚举,我需要将值显示为本地化字符串。 我目前的做法是:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | public enum MyEnum { VALUE1(R.string.VALUE1), VALUE2(R.string.VALUE2), . . VALUE10(R.string.VALUE10); private int mResId = -1; private MuEnum(int resId) { mResId = resId; } public String toLocalizedString(Resources r) { if (-1 != mResId) return (r.getString(mResId)); return (this.toString()); } } |
有没有更简单的方法来做到这一点? 如果我能以某种方式根据枚举值名称(即'VALUE1')查找资源,我会喜欢它。
1 2 3 4 5 6 7 8 | <?xml version="1.0" encoding="utf-8"?> <resources> <string name="VALUE1"/>My string</string> <string name="VALUE2"/>My string 2</string> . . <string name="VALUE10"/>My string 3</string> </resources> |
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
编辑:为了将来参考,这是最适合我的解决方案:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 | public enum MyEnum { VALUE1, VALUE2, . . VALUE10; /** * Returns a localized label used to represent this enumeration value. If no label * has been defined, then this defaults to the result of {@link Enum#name()}. * * <p> The name of the string resource for the label must match the name of the enumeration * value. For example, for enum value 'ENUM1' the resource would be defined as 'R.string.ENUM1'. * * @param context the context that the string resource of the label is in. * @return a localized label for the enum value or the result of name() */ public String getLabel(Context context) { Resources res = context.getResources(); int resId = res.getIdentifier(this.name(),"string", context.getPackageName()); if (0 != resId) { return (res.getString(resId)); } return (name()); } } |
您当然可以使用
1 2 3 | Resources res = getResources(); MyEnum e = MyEnum.VALUE1; String localized = res.getString(res.getIdentifier(e.name(),"string", getPackageName())); |
从View中,您必须将最后一个参数更改为
我认为你所尝试的是好的,除了你不需要每次想要翻译枚举时都将资源参数传递给枚举。
使用该链接子类化Application Class,然后按照这种方法。
改善方案
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | import android.app.Application; public enum MyEnum { VALUE1(R.string.VALUE1), VALUE2(R.string.VALUE2), . . VALUE10(R.string.VALUE10); private int resourceId; private MyEnum(int id) { resourceId = id; } @Override public String toString() { return MyApplication.getApplicationContext().getString(resourceId); } } |
然后调用
1 | select * from Customer where userStatus = MyEnum.VALUEx.toString(); |
这可能会破坏您的应用程序,如果您将枚举值存储为数据库中的VALUE1,VALUE2 ...,那么请记住在不想使用
1 | select * from Customer where userStatus = MyEnum.VALUEx.name(); |
使用静态应用程序总是不好的做法,因为它不仅打破了Instant Run,而且还违背了编程的解耦原则,从而使模块化难以实现。更不用说Android实际上在单个进程中支持多个应用程序。
出于这个原因,我建议为运行时创建的枚举定义一个内部类,只要可以更改语言环境。
1 2 3 4 5 6 7 8 9 10 11 12 13 | enum Example { A(R.string.label_a), B(R.string.label_b); Example(@StringRes int label) { mLabel = label; } private @StringRes int mLabel; class Entry { private Context mContext; Entry(final Context context) { mContext = context; } @Override public String toString() { return mContext.getString(mLabel); } } } |
然后,构建Example.Entry实例或Example.Entry数组,以表示原始枚举的本地化版本。
1 2 3 | Example.A.new Entry(context); Arrays.stream(Example.values()).map(item -> item.new Entry(context)).toArray(Example.Entry[]::new) |
如果你是你的应用程序类的子类,你可以将它作为单例(参见:http://androidcookbook.com/Recipe.seam?recipeId = 1218)一旦你得到你的
单例实例,您可以在toLocalizedString()中使用它来获取资源对象
并摆脱参数:
1 2 3 | public String getString() { return YourApp.getInstance().getResources().getString(resId); } |
瞧 - 现在你看起来很干净。
1 2 3 4 5 | enum class MeasurementEnum(var position: Int, @StringRes var userRedableStringRes: Int) { False(0, R.string.boolean_false), True(1,R.string.boolean_true) } |
首先创建新类:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | import android.app.Application; public class MyApplication extends Application { private static MyApplication singleton; public static MyApplication getInstance(){ return singleton; } @Override public void onCreate() { super.onCreate(); singleton = this; } } |
现在在AndroidManifest.xml中添加对应用程序类的引用:
1 |
接下来创建你的枚举。性别的示例枚举:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 | public enum Gender { MALE(0, R.string.male), FEMALE(1, R.string.female); private Integer resourceId; private Integer index; private static final Map<Integer, Gender> lookupIndex = new HashMap<Integer, Gender>(); private static final Map<Integer, Gender> lookupResourceId = new HashMap<Integer, Gender>(); private static final Map<String, Gender> lookupTranslation = new HashMap<String, Gender>(); static { for (Gender g : values()) { lookupIndex.put(g.getIndex(), g); lookupResourceId.put(g.getResourceId(), g); lookupTranslation.put(g.toString(), g); } } private Gender(Integer index, Integer displayText) { this.resourceId = displayText; this.index = index; } public Integer getIndex() { return this.index; } public Integer getResourceId() { return this.resourceId; } public static Gender findByIndex(Integer index) { return lookupIndex.get(index); } public static Gender findByResourceId(Integer id) { return lookupResourceId.get(id); } public static Gender findByTranslationText(String text) { return lookupTranslation.get(text); } @Override public String toString() { return MyApplication.getInstance().getResources().getString(this.resourceId); }} |
现在您可以使用请求的查找模式:
1 2 3 4 5 6 7 8 9 | // by index Gender male = Gender.findByIndex(0); // by translation String femaleTranslated = context.getResources().getString(R.string.female); Gender gender = Gender.findByTranslationText(femaleTranslated); // by id Gender gender = Gender.findByResourceId(R.string.female); |
特别感谢AhmetYüksektepe