Android,从字符串获取资源ID?


158

我需要将资源ID传递给我的一个类中的方法。它既需要使用引用指向的id,也需要使用字符串。我应该如何最好地做到这一点?

例如:

R.drawable.icon

我需要获取它的整数ID,但是我还需要访问字符串“ icon”。

如果我只需要传递给该方法的是“ icon”字符串,那将是更好的选择。


是否有可能以类似的方式将文件的getId保存到内部存储中?我有问题,因为我应该向我的画廊提供ID数组而不是位置(认为是适配器)..谢谢
Ewoks 2012年

@Ewoks:他们在内部存储中没有ID。它们只是图像,如果您需要将它们加载到一堆Image对象中并传递这些对象,则可能需要提出一个新问题。
哈米德

Answers:


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,然后使用另一个反射查找来获取资源ID。那将解释速度差异。话虽如此,但它们都不是特别快,因此确实需要进行缓存(尤其是在循环中使用,或在中用于行ListView)。反射方法的最大问题是,它对Android内部进行了假设,这些假设可能会在将来的某些版本中发生变化。
CommonsWare 2010年

1
@CommonsWare:是的。我正在检查android的实现方式,最终它还是一个本地调用。gitorious.org/android-eeepc/base/blobs/... => gitorious.org/android-eeepc/base/blobs/...
Macarse

3
我会使用带有ID的整数数组来代替。使用字符串作为ID听起来并不正确。
EboMike 2010年

9
为什么要context参数?
Rudey

14
调用应该是getId(“ icon”,R.drawable.class); 不是getResId(“ icon”,context,Drawable.class);
Smeet

80

您可以使用此功能获取资源ID。

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()。
Ricardo Meneghin Filho

37

这是基于@Macarse的答案。

使用它以更快,更友好的方式获取资源ID。

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

如何从资源名称获取应用程序资源ID是一个非常普遍且可以很好回答的问题。

如何从资源名称获取本机Android资源ID的答案不太好。这是我通过资源名称获取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

如果您需要将字符串和整数配对,那么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


我在下面的回答与此相反。传递资源ID,然后使用getResourceEntryName(id)查找字符串名称。从较长的文本中找到“图标”不会引起混乱。
2014年


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

一种从字符串获取资源ID的简单方法。在这里,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 '16

4

因为您说过您只想传递一个参数,而对哪个参数似乎都不重要,所以可以传递资源标识符,然后找出它的字符串名称,因此:

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

这可能是获得两个值的最有效方法。您不必费心从更长的字符串中查找“ icon”部分。


2

在您的res / layout / my_image_layout.xml中

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

要通过其@ + id值获取该ImageView,请在您的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

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

用法:

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,我使用了以下代码:

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;
    }
}
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.