Android, obtendo o ID do recurso da string?

158

Eu preciso passar um ID de recurso para um método em uma das minhas classes. Ele precisa usar o ID que a referência aponta e também a string. Como devo conseguir isso melhor?

Por exemplo:

R.drawable.icon

Preciso obter o número inteiro disso, mas também preciso acessar a string "icon".

Seria preferível que tudo que eu tivesse que passar para o método fosse a string "icon".

Hamid
fonte
é possível, de maneira semelhante, obter os arquivos salvos no armazenamento interno? Eu tenho problema porque eu deveria fornecer matriz de IDs em vez de locais para minha galeria (pensei que do adaptador) .. obrigado
Ewoks
@ Ewoks: Eles não têm IDs no armazenamento interno. São apenas imagens. Se você precisar carregá-las em um monte de objetos de imagem e passá-los, talvez você queira iniciar uma nova pergunta.
Hamid

Respostas:

171

@EboMike: eu não sabia que Resources.getIdentifier()existia.

Nos meus projetos, usei o seguinte código para fazer isso:

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

Seria usado assim para obter o valor do R.drawable.iconvalor inteiro do recurso

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

Acabei de encontrar uma postagem no blog dizendo que Resources.getIdentifier()é mais lenta do que usar a reflexão como eu. Confira .

Macarse
fonte
8
@Macarse: Atualmente, getIdentifier()tem que fazer duas pesquisas de reflexão. No exemplo acima, você getIdentifier()usaria a reflexão para obter e Drawable.class, em seguida, outra pesquisa de reflexão para obter o ID do recurso. Isso explicaria a diferença de velocidade. Dito isto, nenhum é especialmente rápido e, portanto, realmente precisa ser armazenado em cache (principalmente se usado em um loop ou para linhas em a ListView). E o grande problema da abordagem de reflexão é que ela faz suposições sobre os internos do Android que podem mudar em algum lançamento futuro.
CommonsWare
1
@ CommmonsWare: Isso mesmo. Eu estava verificando como o Android foi implementado e acaba sendo uma chamada nativa. gitorious.org/android-eeepc/base/blobs/… => gitorious.org/android-eeepc/base/blobs/…
Macarse
3
Eu usaria uma matriz inteira com os IDs. Usar cadeias de caracteres para IDs não parece a abordagem correta.
EboMike
9
Por que o contextparâmetro?
Rudey
14
A chamada deve ser getId ("icon", R.drawable.class); não getResId ("ícone", contexto, Drawable.class);
Smeet
80

Você pode usar esta função para obter o ID do recurso.

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

Portanto, se você deseja obter uma função de chamada desenhável como esta

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

e para string você pode chamar assim

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

Leia isso

Azhar
fonte
11
Qual o sentido de criar uma função que simplesmente chame outra e "lide" com uma possível exceção? Ligue diretamente para getResources (). GetIdentifier ().
Ricardo Meneghin Filho
37

Isso é baseado na resposta do @Macarse.

Use isso para obter o ID dos recursos de uma maneira mais rápida e amigável ao código.

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

Exemplo:

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

Como obter um ID de recurso de aplicativo a partir do nome do recurso é uma pergunta bastante comum e bem respondida.

Como obter um ID de recurso Android nativo a partir do nome do recurso é menos bem respondido. Aqui está minha solução para obter um recurso desenhável do Android pelo nome do recurso:

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

O método pode ser modificado para acessar outros tipos de recursos.

Martin Pearman
fonte
agora .getResources () getDrawable está obsoleta. 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

Se você precisar emparelhar uma string e um int, que tal um Mapa?

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

Você pode usar Resources.getIdentifier(), embora você precise usar o formato para sua string como você usa em seus arquivos XML, ou seja package:drawable/icon.

EboMike
fonte
Minha resposta abaixo é o inverso disso. Passe a identificação do recurso e use getResourceEntryName(id)para encontrar o nome da sequência. Não é difícil encontrar "ícone" no texto mais longo.
Steve Waring
8

Eu fiz assim, está funcionando para mim:

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

public int getDrawableName(Context ctx,String str){
    return ctx.getResources().getIdentifier(str,"drawable",ctx.getPackageName());
}
Ivan Vovk
fonte
1
Seria melhor se você desse mais algumas informações à sua resposta.
XMRi 09/10/19
6

Uma maneira simples de obter o ID do recurso da string. Aqui resourceName é o nome do recurso ImageView na pasta drawable que também está incluída no arquivo 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
fonte
Obrigado cara, foi realmente útil .. Eu procurei muito e não consegui. Ao ver sua resposta, descobri que o segundo parâmetro para getIdentifierdeve ser id. Isso nem foi mencionado no site de desenvolvimento do Android. onde você conseguiu essa informação?
Prakash GPZ
4

Como você disse que queria passar apenas um parâmetro e que parecia não importar qual, você poderia passar o identificador de recurso e descobrir o nome da string, assim:

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

Essa pode ser a maneira mais eficiente de obter os dois valores. Você não precisa se preocupar em encontrar apenas a parte "ícone" de uma string mais longa.

Steve Waring
fonte
2

Em seu res / layout / my_image_layout.xml

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

Para capturar esse ImageView pelo seu valor de + id, dentro do seu código java, faça o seguinte:

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);  
Gene
fonte
2

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

Uso:

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

No MonoDroid / Xamarin.Android, você pode:

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

Mas como o GetIdentifier não é recomendado no Android - você pode usar o Reflection assim:

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

onde sugiro colocar um try / catch ou verificar as strings que você está passando.

Daniele D.
fonte
1

Para obter o ID do Drawable do nome do recurso String, estou usando este código:

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
fonte