Android, Ressourcen-ID von Zeichenfolge erhalten?

158

Ich muss eine Ressourcen-ID an eine Methode in einer meiner Klassen übergeben. Es muss sowohl die ID verwenden, auf die die Referenz verweist, als auch die Zeichenfolge. Wie soll ich das am besten erreichen?

Beispielsweise:

R.drawable.icon

Ich muss die Ganzzahl-ID dafür erhalten, aber ich brauche auch Zugriff auf die Zeichenfolge "Symbol".

Es wäre vorzuziehen, wenn ich nur die "Symbol" -String an die Methode übergeben müsste.

Hamid
quelle
Ist es auf ähnliche Weise möglich, die ID von Dateien abzurufen, die im internen Speicher gespeichert sind? Ich habe ein Problem, weil ich meiner Galerie eine Reihe von IDs anstelle von Speicherorten zur Verfügung stellen sollte (dachte, es ist ein Adapter). Danke
Ewoks
@Ewoks: Sie haben keine IDs im internen Speicher. Es handelt sich nur um Bilder. Wenn Sie sie in eine Reihe von Bildobjekten laden und übergeben möchten, möchten Sie möglicherweise eine neue Frage stellen.
Hamid

Antworten:

171

@EboMike: Ich wusste nicht, dass Resources.getIdentifier()es das gibt.

In meinen Projekten habe ich dazu den folgenden Code verwendet:

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

Es würde so verwendet, um den Wert des R.drawable.iconRessourcen-Integer-Werts zu erhalten

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

Ich habe gerade einen Blog-Beitrag gefunden, der besagt, dass er Resources.getIdentifier()langsamer ist als Reflexion wie ich. Schau es dir an .

Macarse
quelle
8
@ Macarse: Derzeit getIdentifier()müssen zwei Reflexionssuchen durchgeführt werden. In Ihrem obigen Beispiel getIdentifier()würden Sie Drawable.classReflection verwenden, um die Ressourcen-ID abzurufen, und dann eine weitere Reflection-Suche, um sie abzurufen. Das würde den Geschwindigkeitsunterschied erklären. Davon abgesehen sind beide nicht besonders schnell und müssen daher wirklich zwischengespeichert werden (insbesondere wenn sie in einer Schleife oder für Zeilen in a verwendet werden ListView). Das große Problem des Reflexionsansatzes besteht darin, dass Annahmen über die Interna von Android getroffen werden, die sich in einer zukünftigen Version ändern könnten.
CommonsWare
1
@ CommonsWare: Das stimmt. Ich habe überprüft, wie Android implementiert ist und es endet damit, dass es sich um einen nativen Anruf handelt. gitorious.org/android-eeepc/base/blobs/… => gitorious.org/android-eeepc/base/blobs/…
Macarse
3
Ich würde stattdessen ein ganzzahliges Array mit den IDs verwenden. Die Verwendung von Zeichenfolgen für IDs klingt nicht nach dem richtigen Ansatz.
EboMike
9
Warum der contextParameter?
Rudey
14
Der Aufruf sollte getId sein ("icon", R.drawable.class); not getResId ("icon", context, Drawable.class);
Smeet
80

Mit dieser Funktion können Sie die Ressourcen-ID abrufen.

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

Also, wenn Sie für Drawable Call-Funktion wie diese erhalten möchten

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

und für String kann man es so nennen

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

Lesen Sie dies

Azhar
quelle
11
Was bringt es, eine Funktion zu erstellen, die einfach eine andere aufruft und eine mögliche Ausnahme "behandelt"? Rufen Sie getResources (). GetIdentifier () direkt auf.
Ricardo Meneghin Filho
37

Dies basiert auf der @ Macarse-Antwort.

Verwenden Sie diese Option, um die Ressourcen-ID schneller und codefreundlicher abzurufen.

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

Beispiel:

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

Das Abrufen einer Anwendungsressourcen- ID aus dem Ressourcennamen ist eine häufig gestellte und gut beantwortete Frage.

Wie eine native Android- Ressourcen-ID aus dem Ressourcennamen abgerufen wird, ist weniger gut beantwortet. Hier ist meine Lösung, um eine Android-Zeichenressource nach Ressourcennamen zu erhalten:

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

Die Methode kann geändert werden, um auf andere Ressourcentypen zuzugreifen.

Martin Pearman
quelle
jetzt .getResources (). getDrawable ist veraltet 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

Wenn Sie einen String und ein Int koppeln müssen, wie wäre es dann mit einer Map?

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
quelle
9

Sie können verwenden Resources.getIdentifier(), obwohl Sie das Format für Ihre Zeichenfolge verwenden müssen, wie Sie es in Ihren XML-Dateien verwenden, dh package:drawable/icon.

EboMike
quelle
Meine Antwort unten ist das Gegenteil davon. Übergeben Sie die Ressourcen-ID und getResourceEntryName(id)suchen Sie dann den Zeichenfolgennamen. Kein Durcheinander, um "Symbol" aus dem längeren Text zu finden.
Steve Waring
8

Mir hat das gefallen, es funktioniert für mich:

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

public int getDrawableName(Context ctx,String str){
    return ctx.getResources().getIdentifier(str,"drawable",ctx.getPackageName());
}
Ivan Vovk
quelle
1
Wäre besser, wenn Sie Ihrer Antwort nur einige weitere Informationen geben würden.
xMRi
6

Eine einfache Möglichkeit, die Ressourcen-ID aus einer Zeichenfolge abzurufen. Hier ist resourceName der Name der Ressource ImageView im zeichnbaren Ordner, der auch in der XML-Datei enthalten ist.

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
quelle
Danke Mann, es war wirklich hilfreich. Ich habe viel gesucht und es nicht funktioniert. Als ich Ihre Antwort sah, stellte ich fest, dass der zweite Parameter für sein getIdentifiermuss id. Dies wurde nicht einmal in Android Dev Site erwähnt. Woher hast du diese Informationen?
Prakash GPz
4

Da Sie sagten, Sie wollten nur einen Parameter übergeben, und es schien nicht wichtig zu sein, welchen, könnten Sie die Ressourcenkennung übergeben und dann den Zeichenfolgennamen dafür herausfinden, also:

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

Dies ist möglicherweise der effizienteste Weg, um beide Werte zu erhalten. Sie müssen nicht herumspielen, um nur den "Symbol" -Teil aus einer längeren Zeichenfolge zu finden.

Steve Waring
quelle
2

In Ihrer res / layout / my_image_layout.xml

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

Gehen Sie folgendermaßen vor, um diese ImageView anhand ihres @ + ID-Werts in Ihrem Java-Code zu erfassen:

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);  
Gen
quelle
2

Der Kotlin-Ansatz

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

Verwendung:

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

In MonoDroid / Xamarin.Android können Sie Folgendes tun:

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

Da GetIdentifier in Android nicht empfohlen wird, können Sie Reflection folgendermaßen verwenden:

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

wo ich vorschlage, einen Versuch / Fang zu machen oder die Zeichenfolgen zu überprüfen, die Sie übergeben.

Daniele D.
quelle
1

Zum Abrufen der Drawable-ID vom String-Ressourcennamen verwende ich diesen 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
quelle