web-dev-qa-db-ja.com

AndroidのEnum文字列リソース検索パターンはありますか?

ローカライズされた文字列として値を表示する必要がある列挙体があります。私の現在のアプローチはこれです:

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」)に基づいてリソースを検索できたら、それが大好きです。

<?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>

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

編集:将来の参考のために、これは私にとって最も効果的な解決策です:

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());
    }
}
37
jsmith

Resources.getIdentifier()を使用すると、リソースを名前で確実に検索できます。たとえば、例として投稿した文字列リソースを使用すると、アクティビティからこれを行うことができます。

_Resources res = getResources();
MyEnum e = MyEnum.VALUE1;
String localized = res.getString(res.getIdentifier(e.name(), "string", getPackageName()));
_

ビューから、最後の引数をgetContext().getPackageName()に変更する必要があります

26
Ted Hopp

Enumを翻訳するたびにresources引数をenumに渡す必要がないことを除いて、あなたが試したものは良いと思います。


link を使用してアプリケーションクラスをサブクラス化し、このアプローチに従います。

より良いソリューション

_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);

    }

}
_

次に_MyEnum.VALUEx_を呼び出すと、常に翻訳された列挙値が得られますただし、これはあなたのことではないかもしれないことに注意してくださいalwaysが必要です。たとえば、次のような生のクエリがあるとします。

_select * from Customer where userStatus = MyEnum.VALUEx.toString();
_

Enum値をVALUE1、VALUE2 ...としてdbに保存している場合、これによりアプリが壊れる可能性があるため、MyEnumの翻訳された値を使用しない場合は、必ずMyEnum.VALUEx.name()を使用してください。

_select * from Customer where userStatus = MyEnum.VALUEx.name();
_
7
dsharew

静的アプリケーションの使用は、Instant Runを無効にするだけでなく、プログラミングの分離原理に反するため、常に悪い習慣です。したがって、モジュール化の実装が困難になります。言うまでもなくAndroidは、実際には単一のプロセスで複数のアプリケーションをサポートしています。

このため、ロケールが変更される可能性がある場合はいつでも、実行時に作成される列挙型の内部クラスを定義することをお勧めします。

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の配列を作成して、元の列挙型のローカライズバージョンを表します。

Example.A.new Entry(context);

Arrays.stream(Example.values()).map(item -> item.new Entry(context)).toArray(Example.Entry[]::new)
3
Oasis Feng

アプリケーションクラスをサブクラス化する場合、それをシングルトンとして持つことができます(http://androidcookbook.com/Recipe.seam?recipeId=1218を参照)。シングルトンインスタンスを取得したら、それをtoLocalizedString()で使用してリソースを取得できます。オブジェクトとパラメーターを取り除く:

 public String getString() {
    return YourApp.getInstance().getResources().getString(resId);
}

出来上がり-見た目がすっきりしたインターフェースになりました。

2

最初に新しいクラスを作成します。

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のアプリケーションクラスへの参照を追加します。

<application ... Android:name="com.yourPackageName.application.MyApplication  ">

次に列挙型を作成します。性別の列挙型の例:

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);
}}

これで、要求されたルックアップパターンを使用できます。

// 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に感謝します

0
lidox
enum class MeasurementEnum(var position: Int, @StringRes
                    var userRedableStringRes: Int) {
    False(0, R.string.boolean_false),
    True(1,R.string.boolean_true)
}
0
Damian JK