Android, obtenir l'ID de ressource à partir de la chaîne?

159

J'ai besoin de transmettre un ID de ressource à une méthode dans l'une de mes classes. Il doit utiliser à la fois l'identifiant vers lequel pointe la référence et la chaîne. Quelle est la meilleure façon d'y parvenir?

Par exemple:

R.drawable.icon

J'ai besoin d'obtenir l'ID entier de ceci, mais j'ai également besoin d'accéder à la chaîne "icon".

Il serait préférable que tout ce que je devais passer à la méthode soit la chaîne "icon".

Hamid
la source
est-il possible de la même manière d'obtenir l'Id des fichiers enregistrés sur le stockage interne? J'ai un problème car je devrais fournir un tableau d'identifiants au lieu d'emplacements dans ma galerie (je pense que c'est un adaptateur) .. merci
Ewoks
@Ewoks: Ils n'ont pas d'identifiant sur le stockage interne. Ce ne sont que des images, si vous avez besoin de les charger dans un groupe d'objets Image et de les transmettre, vous voudrez peut-être commencer une nouvelle question.
Hamid

Réponses:

172

@EboMike: Je ne savais pas que cela Resources.getIdentifier()existait.

Dans mes projets, j'ai utilisé le code suivant pour ce faire:

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

Il serait utilisé comme ceci pour obtenir la valeur de R.drawable.iconla valeur entière de la ressource

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

Je viens de trouver un article de blog disant que Resources.getIdentifier()c'est plus lent que d'utiliser la réflexion comme je l'ai fait. Vérifiez-le .

Macarse
la source
8
@Macarse: Actuellement, getIdentifier()doit faire deux recherches de réflexion. Dans votre exemple ci-dessus, getIdentifier()utiliserait la réflexion pour obtenir Drawable.class, puis une autre recherche de réflexion pour obtenir l'ID de ressource. Cela expliquerait la différence de vitesse. Cela étant dit, ni l'un ni l'autre ne sont particulièrement rapides et ont donc vraiment besoin d'être mis en cache (en particulier s'ils sont utilisés dans une boucle, ou pour les lignes en a ListView). Et le gros problème de l'approche de réflexion est qu'elle émet des hypothèses sur les composants internes d'Android qui pourraient changer dans certaines versions futures.
CommonsWare
1
@CommonsWare: C'est vrai. Je vérifiais comment Android implémenté et cela finit par être un appel natif. gitorious.org/android-eeepc/base/blobs/… => gitorious.org/android-eeepc/base/blobs/…
Macarse
3
J'utiliserais plutôt un tableau d'entiers avec les ID. L'utilisation de chaînes pour les identifiants ne semble pas être la bonne approche.
EboMike
9
Pourquoi le contextparamètre?
Rudey
14
L'appel doit être getId ("icon", R.drawable.class); not getResId ("icône", contexte, Drawable.class);
Smeet le
80

Vous pouvez utiliser cette fonction pour obtenir l'ID de ressource.

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

Donc, si vous voulez obtenir une fonction d'appel dessinable comme celle-ci

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

et pour la chaîne, vous pouvez l'appeler comme ça

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

Lis ça

Azhar
la source
11
Quel est l'intérêt de créer une fonction qui en appelle simplement une autre et "gère" une éventuelle exception? Appelez directement getResources (). GetIdentifier ().
Ricardo Meneghin Filho
37

Ceci est basé sur la réponse @Macarse.

Utilisez-le pour obtenir l'ID des ressources d'une manière plus rapide et plus conviviale.

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

Exemple:

getId("icon", R.drawable.class);
Daniel De León
la source
30

Comment obtenir un identifiant de ressource d' application à partir du nom de la ressource est une question assez courante et bien répondue.

Comment obtenir un identifiant de ressource Android natif à partir du nom de la ressource est moins bien répondu. Voici ma solution pour obtenir une ressource dessinable Android par nom de ressource:

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

La méthode peut être modifiée pour accéder à d'autres types de ressources.

Martin Pearman
la source
now .getResources (). getDrawable est obsolète 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

Si vous avez besoin de coupler une chaîne et un int, que diriez-vous d'une carte?

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);
}
Peter Knego
la source
9

Vous pouvez utiliser Resources.getIdentifier(), bien que vous deviez utiliser le format de votre chaîne tel que vous l'utilisez dans vos fichiers XML, c'est-à-dire package:drawable/icon.

EboMike
la source
Ma réponse ci-dessous est l'inverse. Transmettez l'ID de ressource, puis utilisez getResourceEntryName(id)pour rechercher le nom de la chaîne. Pas de problème pour trouver "icône" dans le texte plus long.
Steve Waring
8

J'ai fait comme ça, ça marche pour moi:

    imageView.setImageResource(context.getResources().
         getIdentifier("drawable/apple", null, context.getPackageName()));
Sarvar Nishonboev
la source
7
Simple method to get resource ID:

public int getDrawableName(Context ctx,String str){
    return ctx.getResources().getIdentifier(str,"drawable",ctx.getPackageName());
}
Ivan Vovk
la source
1
Ce serait mieux si vous donniez simplement plus d'informations à votre réponse.
xMRi
6

Un moyen simple d'obtenir l'ID de ressource à partir d'une chaîne. Ici, resourceName est le nom de la ressource ImageView dans le dossier dessinable qui est également inclus dans le fichier 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);
Muhammad Adil
la source
Merci mec, c'était vraiment utile ... J'ai beaucoup cherché et je n'ai pas réussi. En voyant votre réponse, j'ai trouvé que le deuxième paramètre pour getIdentifierdoit être id. Cela n'a même pas été mentionné sur le site de développement Android. où avez-vous cette information?
Prakash GPz
4

Puisque vous avez dit que vous ne vouliez passer qu'un seul paramètre et que peu importe lequel, vous pouvez passer l'identificateur de ressource, puis trouver le nom de la chaîne, ainsi:

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

Cela pourrait être le moyen le plus efficace d'obtenir les deux valeurs. Vous n'avez pas à vous soucier de trouver uniquement la partie "icône" d'une chaîne plus longue.

Steve Waring
la source
2

Dans votre res / layout / my_image_layout.xml

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

Pour saisir cette ImageView par sa valeur @ + id, dans votre code java, procédez comme suit:

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);  
Gène
la source
2

L'approche 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
            }
        }

Usage:

val resId = R.drawable::class.java.getId("icon")
Arsenius
la source
1

Dans MonoDroid / Xamarin.Android, vous pouvez faire:

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

Mais depuis GetIdentifier, ce n'est pas recommandé dans Android - vous pouvez utiliser Reflection comme ceci:

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

où je suggère de mettre un essai / attraper ou de vérifier les cordes que vous passez.

Daniele D.
la source
1

Pour obtenir l'identifiant Drawable à partir du nom de la ressource String, j'utilise ce code:

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;
    }
}
bitvale
la source