Tengo una enumeración donde tengo que mostrar los valores como cadenas localizadas. Mi enfoque actual ha sido este:

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

¿Hay alguna manera más fácil de hacer esto? Me encantaría que si de alguna manera podría buscar el recurso basado en el valor de enumeración nombre (he.e ‘VALOR1’).

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

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

EDIT: Sólo para referencia en el futuro, esta es la solución que ha funcionado mejor para mí:

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());
    }
}
InformationsquelleAutor jsmith | 2012-03-16

6 Comentarios

  1. 21

    Que sin duda puede buscar un recurso por su nombre, utilizando Resources.getIdentifier(). Por ejemplo, con los recursos de cadena publicado como un ejemplo, usted puede hacer esto a partir de una actividad:

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

    Desde un punto de Vista, habría que cambiar el último argumento de getContext().getPackageName()

    • ¿Hay alguna razón por qué no simplemente se inyecte directamente el nombre del paquete de la enumeración es en lugar de ‘getPackageName()’? Lo pregunto porque mi enum es en una biblioteca compartida por varios proyectos.
    • Esa es precisamente la razón por la que usted no quiere inyectar el nombre del paquete directamente. El nombre del paquete que va allí es el nombre declarado en el manifiesto, no en el paquete que la enumeración es en.
    • Me miró a los paquetes generados dentro de las aplicaciones que usan la biblioteca, y creo que entiendo lo que quieres decir. Pero, me gustaría una explicación de cómo embalaje trabaja con banas bibliotecas. Puede que referencia me documentación sobre esto?
    • Seguro. Leer acerca de los proyectos de la biblioteca aquí. Además de la documentación para la AndroidManifest.xml archivo, el blog de Cosas Que No puede Cambiar es bien vale la pena leer.
    • En lugar de getPackageName() también puede utilizar BuildConfig.APPLICATION_ID y ahorrarse el contexto de problemas.
    • sólo está disponible para Gradle/Android Studio se basa. No está definido para otras versiones.
    • Es bueno saberlo! Pero Android Studio parece el camino a seguir para futuros proyectos 😉
    • Tal vez así. Yo todavía uso del TDA/Eclipse. Pero sospecho que BuildConfig.APPLICATION_ID es malo incluso para Gradle construye. Si el código en cuestión es parte de una biblioteca, el IDENTIFICADOR de la aplicación depende de lo que el proyecto utiliza la biblioteca y no se conoce en tiempo de compilación. Creo que lo hará uso de la biblioteca declarado nombre de la aplicación y el nombre equivocado, serán compilados en-línea en el archivo de clase generada.

  2. 6

    Yo creo que lo que han intentado es bueno, excepto que usted no necesita pasar los recursos argumento a la enumeración cada vez que usted quiere traducir la enumeración.


    Utilizar el enlace a crear una subclase de la Clase de la Aplicación, a continuación, siga este enfoque.

    Mejor Solución

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

    , A continuación, llamar a MyEnum.VALUEx siempre te dará la traducción de un valor de enumeración, pero cuidado, esto podría no ser lo que usted desea siempre e.g puede tener una prima de consulta como esta:

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

    Esto puede romper tu aplicación, si usted está almacenando los valores de enumeración como VALOR1, VALOR2… en db, así que recuerda usar este MyEnum.VALUEx.name() cuando usted no quiere utilizar la traducción del valor de su MyEnum.

    select * from Customer where userStatus = MyEnum.VALUEx.name();
    • ¿Qué es «Miaplicacion» ? Si llevo a mi iniciador de la actividad que se extiende AppCompatActivity, obtengo el siguiente error: No-método estático «getApplicationCOntext()
    • Ok yo tengo: stackoverflow.com/a/27416998/1386969
  3. 3

    Uso estático de la Aplicación es siempre una mala práctica, porque no sólo se rompe Instantánea, pero también esto está en contra de la disociación principio de programación, lo que hace que la modularización difícil de implementar. Por no hablar de Android que realmente soporta múltiples Aplicaciones en un único proceso.

    Por esta razón, te sugiero que definir una clase interna de la enumeración a ser creado en tiempo de ejecución, siempre que la configuración regional puede ser cambiado.

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

    Entonces, construir Ejemplo.La entrada de la instancia o de la matriz de Ejemplo.Entrada para representar la versión traducida de la original enum.

    Example.A.new Entry(context);
    
    Arrays.stream(Example.values()).map(item -> item.new Entry(context)).toArray(Example.Entry[]::new)
  4. 2

    Si subclase de la clase de aplicación, usted puede tener como singleton ( ver:http://androidcookbook.com/Receta.costura?recipeId=1218 ) una Vez que tienes tu
    singleton ejemplo , se puede utilizar en toLocalizedString() para obtener los recursos objeto de
    y deshacerse de parámetro:

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

    voila – ahora tienes limpia interfaz de aspecto.

    • Mi enum es parte de una biblioteca utilizada por varias aplicaciones. Esto vendría a ser tedioso. Yo no tengo un problema que pasa en un valor.
    • Pero su Identificadores de recursos que no son portables entre aplicaciones.
  5. 0

    Crear primero de una nueva clase:

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

    Ahora agregar la referencia a la clase de aplicación en AndroidManifest.xml:

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

    Siguiente crear su enumeración. Ejemplo de enumeración de género:

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

    Ahora usted puede utilizar el solicitado la búsqueda de patrón:

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

    Speacial gracias a Ahmet Yüksektepe

  6. 0
    enum class MeasurementEnum(var position: Int, @StringRes
    var userRedableStringRes: Int) {
    False(0, R.string.boolean_false),
    True(1,R.string.boolean_true)
    }
    • Mientras este comando puede responder a la pregunta, proporcionar contexto adicional acerca de por qué y/o cómo este código responde a la pregunta que mejora su valor de largo plazo

Dejar respuesta

Please enter your comment!
Please enter your name here