Android, получить идентификатор ресурса из строки?

159

Мне нужно передать идентификатор ресурса в метод в одном из моих классов. Необходимо использовать как идентификатор, на который указывает ссылка, так и строку. Как мне лучше всего достичь этого?

Например:

R.drawable.icon

Мне нужно получить целочисленный идентификатор этого, но мне также нужен доступ к строке «значок».

Было бы предпочтительнее, если бы все, что я должен был передать методу, это строка "icon".

Хамид
источник
Возможно ли аналогичным способом получить файлы, сохраненные во внутреннем хранилище? У меня проблема, потому что я должен предоставить массив идентификаторов вместо местоположений для моей галереи (думал, что это адаптер) .. спасибо
Ewoks
@Ewoks: у них нет идентификаторов на внутреннем хранилище. Это просто изображения, если вам нужно загрузить их в кучу объектов Image и передать их, вы можете начать новый вопрос.
Хамид

Ответы:

172

@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()это медленнее, чем использование отражения, как я сделал. Проверьте это .

Macarse
источник
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параметр?
Руди
14
Вызов должен быть getId ("icon", R.drawable.class); не getResId ("значок", контекст, Drawable.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, тогда как насчет 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);
}
Питер Кнего
источник
9

Вы можете использовать Resources.getIdentifier(), хотя вы должны использовать формат для строки , как вы использовать его в XML - файлах, то есть package:drawable/icon.

EboMike
источник
Мой ответ ниже обратный. Передайте идентификатор ресурса, а затем используйте, 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. откуда ты взял эту информацию?
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);

где я предлагаю поставить попытку / поймать или проверить строки, которые вы передаете.

Даниэль Д.
источник
1

Для получения Drawable 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;
    }
}
bitvale
источник