Android, отримуючи ідентифікатор ресурсу з рядка?


158

Мені потрібно передати ідентифікатор ресурсу методу в одному з моїх класів. Для цього потрібно використовувати ідентифікатор, на який вказують посилання, а також потрібний рядок. Як мені найкраще цього досягти?

Наприклад:

R.drawable.icon

Мені потрібно отримати цілий ідентифікатор цього, але мені також потрібен доступ до рядка "icon".

Краще, якби все, що мені довелося передати методу, - це рядок "icon".


чи можна подібним чином отриматиId файлів, збережених у внутрішньому сховищі? У мене є проблема, тому що я повинен поставити масив ідентифікаторів замість місцеположень до моєї галереї (думав, що це адаптер) .. дякую
Ewoks

@Ewoks: у них немає ідентифікаторів у внутрішній пам’яті. Вони просто зображення, якщо все, що вам потрібно, щоб завантажити їх у купу об’єктів зображення та передати їх, можливо, ви захочете почати нове запитання.
Хамід

Відповіді:


171

@EboMike: Я не знав, що Resources.getIdentifier()існує.

У своїх проектах я для цього використовував такий код:

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

Це було б використано таким чином для отримання значення R.drawable.iconцілого значення ресурсу

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

Я щойно знайшов повідомлення в блозі, в якому говорилося, що Resources.getIdentifier()це повільніше, ніж використання рефлексії, як я. Перевірте це .


8
@Macarse: На сьогоднішній день getIdentifier()потрібно зробити два пошуку. У вашому прикладі вище, getIdentifier()використовуйте відображення для отримання Drawable.class, а потім інший пошук відображення, щоб отримати ідентифікатор ресурсу. Це пояснювало б різницю швидкостей. Незважаючи на те, що вони не є особливо швидкими, тому їх потрібно дійсно кешувати (особливо якщо це використовується в циклі або для рядків у a ListView). І великою проблемою підходу до роздумів є те, що він робить припущення щодо внутрішніх систем Android, які можуть змінитись у майбутньому випуску.
CommonsWare

1
@CommonsWare: Правильно. Я перевіряв, як Android реалізується, і це закінчується як рідний дзвінок. gitorious.org/android-eeepc/base/blobs/… => gitorious.org/android-eeepc/base/blobs/…
Macarse

3
Я б замість цього використовував цілий масив із ідентифікаторами. Використання рядків для ідентифікаторів не здається правильним підходом.
EboMike

9
Чому contextпараметр?
Rudey

14
Виклик повинен бути getId ("icon", R.dravable.class); not getResId ("значок", контекст, Dravable.class);
Сміт

80

Ви можете використовувати цю функцію для отримання ідентифікатора ресурсу.

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

Тож якщо ви хочете отримати функцію драйвового дзвінка, як це

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

а для рядка ви можете назвати це так

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

Прочитай це


11
Який сенс зробити функцію, яка просто викликає іншу та "обробляє" можливий виняток? Зателефонуйте getResources (). GetIdentifier () безпосередньо.
Рікардо Менегін Філхо

37

Це ґрунтується на відповіді @Macarse.

Використовуйте це, щоб отримати швидше ідентифікатор ресурсів.

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

Приклад:

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

30

Як отримати ідентифікатор ресурсу програми від імені ресурсу - досить поширене і добре відповідне питання.

Як отримати власний ідентифікатор ресурсу Android від імені ресурсу, відповідь менш вдалий. Ось моє рішення отримати доступний драйвер для Android за назвою ресурсу:

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

Метод можна модифікувати для доступу до інших типів ресурсів.


зараз .getResources (). getDrawable застаріло 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

Якщо вам потрібно спарити рядок і int, то як щодо карти?

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

Ви можете використовувати Resources.getIdentifier(), хоча формат для рядка потрібно використовувати так, як ви його використовуєте у своїх XML-файлах, тобто package:drawable/icon.


Моя відповідь нижче - це зворотний бік цього. Передайте ідентифікатор ресурсу та використовуйте getResourceEntryName(id)для пошуку назви рядка. Не возиться, щоб знайти "ікону" з більш тривалого тексту.
Стів Варінг

8

Мені це подобалося, це працює для мене:

    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
Було б краще, якщо ви просто дасте більше інформації на свою відповідь.
xMRi

6

Простий спосіб отримати ідентифікатор ресурсу з рядка. Тут resourceName - назва ресурсу ImageView у папці, що виводиться, яка також входить у файл 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);

Спасибі людині, це було дуже корисно .. Я багато шукав і не працював. Бачачи вашу відповідь, я виявив, що другим параметром для getIdentifierповинен бути id. Про це навіть не згадували на сайті Android android. звідки ви взяли цю інформацію?
Prakash GPz

4

Оскільки ви сказали, що хочете передати лише один параметр, і, здається, це не має значення, ви можете передати ідентифікатор ресурсу, а потім дізнатись ім'я рядка для цього, таким чином:

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

Це може бути найефективнішим способом отримання обох значень. Вам не доведеться возитися з пошуком лише частини «піктограми» з довшої струни.


2

У вашому res / layout / my_image_layout.xml

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

Щоб схопити цей ImageView за його значенням + + id, всередині коду Java виконайте це:

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

Підхід Котліна

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

Використання:

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

1

У MonoDroid / Xamarin.Android ви можете:

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

Але оскільки GetIdentifier не рекомендується в Android - ви можете використовувати Reflection так:

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

де я пропоную поставити спробувати / catch або перевірити рядки, які ви проходите.


1

Для отримання Dravable id від імені ресурсу String я використовую цей код:

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;
    }
}
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.