Android, ottenere l'ID risorsa dalla stringa?


158

Devo passare un ID risorsa a un metodo in una delle mie classi. Deve utilizzare sia l'id a cui punta il riferimento sia anche la stringa. Come dovrei raggiungere questo obiettivo al meglio?

Per esempio:

R.drawable.icon

Devo ottenere l'ID intero di questo, ma ho anche bisogno dell'accesso alla stringa "icona".

Sarebbe preferibile che tutto ciò che dovevo passare al metodo fosse la stringa "icona".


è possibile in modo simile ottenere getId di file salvati nella memoria interna? Ho un problema perché dovrei fornire una serie di ID invece di posizioni alla mia galleria (pensavo che fosse un adattatore) .. grazie
Ewoks

@Ewoks: non hanno ID nella memoria interna. Sono solo immagini, se qualcosa ti serve per caricarle in un gruppo di oggetti Image e passare quelli, potresti voler iniziare una nuova domanda.
Hamid,

Risposte:


171

@EboMike: non sapevo che Resources.getIdentifier()esistesse.

Nei miei progetti ho usato il seguente codice per farlo:

public static int getResId(String resName, Class<?> c) {

    try {
        Field idField = c.getDeclaredField(resName);
        return idField.getInt(idField);
    } catch (Exception e) {
        e.printStackTrace();
        return -1;
    } 
}

Sarebbe usato in questo modo per ottenere il valore del R.drawable.iconvalore intero della risorsa

int resID = getResId("icon", R.drawable.class); // or other resource class

Ho appena trovato un post sul blog che dice che Resources.getIdentifier()è più lento dell'uso della riflessione come ho fatto io. Dai un'occhiata .


8
@Macarse: al momento, getIdentifier()deve fare due ricerche di riflessione. Nel tuo esempio sopra, getIdentifier()utilizzerei la riflessione per ottenere Drawable.class, quindi un'altra ricerca della riflessione per ottenere l'ID della risorsa. Ciò spiegherebbe la differenza di velocità. Detto questo, nessuno dei due è particolarmente veloce e quindi deve davvero essere memorizzato nella cache (in particolare se utilizzato in un ciclo o per le righe in a ListView). E il grande problema dell'approccio di riflessione è che fa ipotesi sugli interni di Android che potrebbero cambiare in alcune versioni future.
CommonsWare il

1
@CommonsWare: Esatto. Stavo controllando come Android ha implementato e finisce per essere una chiamata nativa. gitorious.org/android-eeepc/base/blobs/… => gitorious.org/android-eeepc/base/blobs/…
Macarse

3
Vorrei invece utilizzare un array intero con gli ID. L'uso delle stringhe per gli ID non sembra l'approccio giusto.
EboMike,

9
Perché il contextparametro
Rudey,

14
La chiamata dovrebbe essere getId ("icon", R.drawable.class); not getResId ("icona", contesto, Drawable.class);
Smeet,

80

È possibile utilizzare questa funzione per ottenere l'ID risorsa.

public static int getResourceId(String pVariableName, String pResourcename, String pPackageName) 
{
    try {
        return getResources().getIdentifier(pVariableName, pResourcename, pPackageName);
    } catch (Exception e) {
        e.printStackTrace();
        return -1;
    } 
}

Quindi, se si desidera ottenere una funzione di chiamata disegnabile come questa

getResourceId("myIcon", "drawable", getPackageName());

e per stringa puoi chiamarlo così

getResourceId("myAppName", "string", getPackageName());

Leggi questo


11
Qual è il punto di creare una funzione che semplicemente chiama un'altra e "gestisce" una possibile eccezione? Chiama getResources (). GetIdentifier () direttamente.
Ricardo Meneghin Filho,

37

Questo si basa sulla risposta @Macarse.

Usa questo per ottenere l'ID delle risorse in un modo più veloce e intuitivo.

public static int getId(String resourceName, Class<?> c) {
    try {
        Field idField = c.getDeclaredField(resourceName);
        return idField.getInt(idField);
    } catch (Exception e) {
        throw new RuntimeException("No resource ID found for: "
                + resourceName + " / " + c, e);
    }
}

Esempio:

getId("icon", R.drawable.class);

30

Come ottenere un ID risorsa applicazione dal nome della risorsa è una domanda abbastanza comune e ben risolta.

Come ottenere un ID risorsa nativo Android dal nome della risorsa ha una risposta meno efficace. Ecco la mia soluzione per ottenere una risorsa estraibile Android per nome risorsa:

public static Drawable getAndroidDrawable(String pDrawableName){
    int resourceId=Resources.getSystem().getIdentifier(pDrawableName, "drawable", "android");
    if(resourceId==0){
        return null;
    } else {
        return Resources.getSystem().getDrawable(resourceId);
    }
}

Il metodo può essere modificato per accedere ad altri tipi di risorse.


ora .getResources (). getDrawable è obsoleto if(android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.LOLLIPOP){ return mContext.getDrawable(resourceId); } else { return mContext.getResources().getDrawable(resourceId); }
Evilripper

11

Se hai bisogno di accoppiare una stringa e un int, che ne dici di una mappa?

static Map<String, Integer> icons = new HashMap<String, Integer>();

static {
    icons.add("icon1", R.drawable.icon);
    icons.add("icon2", R.drawable.othericon);
    icons.add("someicon", R.drawable.whatever);
}

9

Puoi usare Resources.getIdentifier(), anche se devi usare il formato per la tua stringa mentre lo usi nei tuoi file XML, ad es package:drawable/icon.


La mia risposta qui sotto è il contrario. Passare l'id risorsa, quindi utilizzare getResourceEntryName(id)per trovare il nome della stringa. Nessun pasticcio per trovare "icona" dal testo più lungo.
Steve Waring,

8

Mi è piaciuto, funziona per me:

    imageView.setImageResource(context.getResources().
         getIdentifier("drawable/apple", null, context.getPackageName()));

7
Simple method to get resource ID:

public int getDrawableName(Context ctx,String str){
    return ctx.getResources().getIdentifier(str,"drawable",ctx.getPackageName());
}

1
Sarebbe meglio se solo dessi qualche informazione in più alla tua risposta.
xMRi

6

Un modo semplice per ottenere l'ID risorsa dalla stringa. Qui resourceName è il nome della risorsa ImageView nella cartella disegnabile che è inclusa anche nel file XML.

int resID = getResources().getIdentifier(resourceName, "id", getPackageName());
ImageView im = (ImageView) findViewById(resID);
Context context = im.getContext();
int id = context.getResources().getIdentifier(resourceName, "drawable",
context.getPackageName());
im.setImageResource(id);

Grazie amico è stato davvero utile .. Ho cercato molto e non ho funzionato. Vedendo la tua risposta, ho scoperto che il secondo parametro per getIdentifierdeve essere id. Questo non è stato nemmeno menzionato nel sito di sviluppo Android. dove hai preso quelle informazioni?
Prakash GPz,

4

Dal momento che hai detto che volevi solo passare un parametro e non sembrava importare quale, potresti passare l'identificatore di risorsa e quindi scoprire il nome della stringa per esso, quindi:

String name = getResources().getResourceEntryName(id);

Questo potrebbe essere il modo più efficiente per ottenere entrambi i valori. Non devi preoccuparti di trovare solo la parte "icona" da una stringa più lunga.


2

Nel tuo res / layout / my_image_layout.xml

<LinearLayout ...>
    <ImageView
        android:id="@+id/row_0_col_7"
      ...>
    </ImageView>
</LinearLayout>

Per afferrare ImageView per il suo valore @ + id, nel tuo codice java fai questo:

String row = "0";
String column= "7";
String tileID = "row_" + (row) + "_col_" + (column);
ImageView image = (ImageView) activity.findViewById(activity.getResources()
                .getIdentifier(tileID, "id", activity.getPackageName()));

/*Bottom code changes that ImageView to a different image. "blank" (R.mipmap.blank) is the name of an image I have in my drawable folder. */
image.setImageResource(R.mipmap.blank);  

2

L'approccio di Kotlin

inline fun <reified T: Class<R.drawable>> T.getId(resourceName: String): Int {
            return try {
                val idField = getDeclaredField (resourceName)
                idField.getInt(idField)
            } catch (e:Exception) {
                e.printStackTrace()
                -1
            }
        }

Uso:

val resId = R.drawable::class.java.getId("icon")

1

In MonoDroid / Xamarin.Android puoi fare:

 var resourceId = Resources.GetIdentifier("icon", "drawable", PackageName);

Ma poiché GetIdentifier non è raccomandato in Android, puoi usare Reflection in questo modo:

 var resourceId = (int)typeof(Resource.Drawable).GetField("icon").GetValue(null);

dove ti consiglio di provare / catturare o verificare le stringhe che stai passando.


1

Per ottenere l'ID Drawable dal nome della risorsa String sto usando questo codice:

private int getResId(String resName) {
    int defId = -1;
    try {
        Field f = R.drawable.class.getDeclaredField(resName);
        Field def = R.drawable.class.getDeclaredField("transparent_flag");
        defId = def.getInt(null);
        return f.getInt(null);
    } catch (NoSuchFieldException | IllegalAccessException e) {
        return defId;
    }
}
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.