Jak uzyskać identyfikator zasobu obrazu, jeśli znam jego nazwę? [duplikować]

Odpowiedzi:

270

Z czymś takim:

String mDrawableName = "myappicon";
int resID = getResources().getIdentifier(mDrawableName , "drawable", getPackageName());
Francesco Laurita
źródło
10
Dzięki, pomogło mi to znaleźć rozwiązanie podobnego problemu! Użyję getResources().getIdentifier(name, "id", getPackageName());aby uzyskać identyfikator danego ImageButton (tak jak z R.id.name).
Select0r
42
Zwróć uwagę, że nazwa do rysowania NIE powinna zawierać rozszerzenia, takiego jak „.png”
larham1
1
co dokładnie zawiera zmienna name? Chcę znaleźć identyfikator przycisku, którego odniesienie znam, w moim przypadku jest tobutton1
John Watson
1
getResource()i getPackageName()pokazuje błąd. cannot resolve method
Srujan Barai
@Srujan Barai getResource()i getPackageName()są metodami z Activity.
Berga
29

Możesz także spróbować tego:

try {
    Class res = R.drawable.class;
    Field field = res.getField("drawableName");
    int drawableId = field.getInt(null);
}
catch (Exception e) {
    Log.e("MyTag", "Failure to get drawable id.", e);
}

Skopiowałem te kody źródłowe z poniższego adresu URL. Na podstawie testów przeprowadzonych na tej stronie jest 5 razy szybszy niż getIdentifier (). Uważam też, że jest bardziej poręczny i łatwy w użyciu. Mam nadzieję, że ci to pomoże.

Link: Dynamiczne pobieranie zasobów w systemie Android

VSB
źródło
2
to może być szybsze, ale odkryłem, że może to przysporzyć ci kłopotów, jeśli używasz proguard. To nie zadziałało w proguard przynajmniej dla mnie
Pedro Rainho
Łapanie ogólnych wyjątków to szczególnie zły pomysł. Ponadto należy zauważyć, że jeśli nie ma twardych odniesień do tego, co można narysować, Proguard może zoptymalizować odniesienie, ponieważ nie wierzy, że jest używane w dowolnym miejscu.
Paul Lammertsma
Rozumiem teraz :) masz na myśli, że podczas optymalizacji zmiany drawableName i zasobu nie można znaleźć za pomocą tej metody, jeśli mam rację? :)
VSB
1
@VSB: jeśli Twój ostatni komentarz jest odpowiedzią na komentarz Paula Lammertsmy bezpośrednio powyżej: Nie, oznacza to, że Proguard nie wie, że jest to odniesienie do zasobu, więc może usunąć zasób, uznając, że nie jest używany.
ToolmakerSteve
kiedy użyjesz xxxxhdpi, xxhdpi itp. ta metoda staje się mniej użyteczna
Someone Somewhere.
11

Przykład publicznego zasobu systemowego:

// this will get id for android.R.drawable.ic_dialog_alert
int id = Resources.getSystem().getIdentifier("ic_dialog_alert", "drawable", "android");

alarm

Innym sposobem jest odwołanie się do dokumentacji klasy android.R.drawable .

naXa
źródło
1
@Milaaaad co masz na myśli?
naXa
to znaczy, że
jestem
1
@Milaaaad Ta metoda jest przeznaczona dla zasobów systemowych. Nie zależą od kontekstu.
naXa
10

Możesz użyć tej funkcji, aby uzyskać identyfikator zasobu:

public static int getResourseId(Context context, String pVariableName, String pResourcename, String pPackageName) throws RuntimeException {
    try {
        return context.getResources().getIdentifier(pVariableName, pResourcename, pPackageName);
    } catch (Exception e) {
        throw new RuntimeException("Error getting Resource ID.", e)
    } 
}


Więc jeśli chcesz uzyskać identyfikator zasobu do rysowania , możesz wywołać metodę w następujący sposób:

getResourseId(MyActivity.this, "myIcon", "drawable", getPackageName());

(lub z fragmentu):

getResourseId(getActivity(), "myIcon", "drawable", getActivity().getPackageName());


Dla String Zasobami ID można nazwać tak:

getResourseId(getActivity(), "myAppName", "string", getActivity().getPackageName());

itp...


Ostrożnie : zgłasza RuntimeException, jeśli nie znajdzie identyfikatora zasobu. Pamiętaj, aby prawidłowo odzyskać siły podczas produkcji.

Przeczytaj to

Azhar
źródło
4
Myślę, że musisz się staticz tego usunąć , inaczej getResources()nie zadziała.
Richard Le Mesurier
@Richard Le Mesurier, czy możesz wyjaśnić dlaczego? Dziękuję Ci.
Veer
1
@ Leo.Han W czasie, gdy napisałem ten komentarz, plik Contextnie był dostępny. Naprawiono albo usunięcie statici przeniesienie go do Context(np. ActivityLub Application); lub alternatywną poprawką jest to, co Jonathan zrobił w swojej edycji, czyli przekazanie a Contextdo metody.
Richard Le Mesurier
1
@Richard Le Mesurier, właśnie sprawdziłem historię edycji, jest tak, jak powiedziałeś, dziękuję za uprzejmą odpowiedź po tylu latach :)
Veer
0

Jeszcze jeden scenariusz, z którym się spotkałem.

String imageName = "Hello", a następnie, gdy zostanie przekazany do funkcji getIdentifier jako pierwszy argument, przekaże nazwę z zakończeniem łańcucha o wartości null i zawsze zwróci zero. Przekaż ten imageName.substring (0, imageName.length () - 1)

sunil shah
źródło