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

Posted

技术标签:

【中文标题】Android,从字符串中获取资源ID?【英文标题】:Android, getting resource ID from string? 【发布时间】:2011-05-24 13:53:29 【问题描述】:

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

例如:

R.drawable.icon

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

如果我必须传递给该方法的只是“图标”字符串,那就更好了。

【问题讨论】:

是否有可能以类似的方式获取保存到内部存储的文件的 ID?我有问题,因为我应该向我的画廊提供 ID 数组而不是位置(认为它是适配器).. 谢谢 @Ewoks:他们在内部存储上没有 ID。它们只是图像,如果您需要将它们加载到一堆 Image 对象中并传递它们,您可能想要开始一个新问题。 How to get a resource id with a known resource name? 的可能重复项 【参考方案1】:

@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() 比使用反射慢。 Check it out.

【讨论】:

@Macarse:目前,getIdentifier() 必须进行两次反射查找。在上面的示例中,getIdentifier() 将使用反射来获取 Drawable.class,然后使用另一个反射查找来获取资源 ID。这将解释速度差异。话虽如此,两者都不是特别快,因此确实需要缓存(特别是如果在循环中使用,或者用于ListView 中的行)。反射方法的一个大问题是它对 android 的内部结构做出了假设,这些假设可能会在未来的某个版本中发生变化。 @CommonsWare:没错。我正在检查android是如何实现的,它最终是一个本地调用。 gitorious.org/android-eeepc/base/blobs/… => gitorious.org/android-eeepc/base/blobs/… 我会使用带有 ID 的整数数组。对 ID 使用字符串听起来不是正确的方法。 为什么要使用context 参数? 调用应该是getId("icon", R.drawable.class); not getResId("icon", context, Drawable.class);【参考方案2】:

你可以使用这个函数来获取资源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;
     

所以如果你想获得 drawable 这样的调用函数

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

对于字符串,你可以这样称呼它

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

Read this

【讨论】:

创建一个简单地调用另一个函数并“处理”可能的异常的函数有什么意义?直接调用getResources().getIdentifier()。 赞成阐明如何传递类型以获取不同的种类或资源。 android dev 文档没有详细信息,并且先前答案中的“id”不适用于字符串。 是否也有相反的情况?从R.string.some_string 到“some_string”的含义?【参考方案3】:

这是基于@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);

【讨论】:

【参考方案4】:

如何从资源名称中获取 应用程序 资源 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 &gt;= android.os.Build.VERSION_CODES.LOLLIPOP) return mContext.getDrawable(resourceId); else return mContext.getResources().getDrawable(resourceId); 【参考方案5】:

如果你需要配对一个字符串和一个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);

【讨论】:

【参考方案6】:

我喜欢这样做,它对我有用:

    imageView.setImageResource(context.getResources().
         getIdentifier("drawable/apple", null, context.getPackageName()));

【讨论】:

谢谢。按预期工作。我使用了以下内容:view.context.resources.getIdentifier("drawable/item_car_$position", null, context.packageName).【参考方案7】:
Simple method to get resource ID:

public int getDrawableName(Context ctx,String str)
    return ctx.getResources().getIdentifier(str,"drawable",ctx.getPackageName());

【讨论】:

如果您在答案中提供更多信息会更好。【参考方案8】:

您可以使用Resources.getIdentifier(),尽管您需要使用在 XML 文件中使用字符串的格式,即package:drawable/icon

【讨论】:

我在下面的回答与此相反。传入资源id,然后使用getResourceEntryName(id)查找字符串名称。从较长的文本中找到“图标”并不麻烦。【参考方案9】:

既然你说你只想传递一个参数,而且似乎并不重要,你可以传入资源标识符,然后找出它的字符串名称,因此:

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

这可能是获取这两个值的最有效方式。您不必在较长的字符串中只找到“图标”部分。

【讨论】:

【参考方案10】:

从字符串中获取资源 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 开发网站中甚至都没有提到。你从哪里得到这些信息的?【参考方案11】:

Kotlin 方法

inline fun <reified T: Class<*>> 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")

或者:

val resId = R.id::class.java.getId("viewId")

【讨论】:

这行得通,但它到底在做什么?它有一个非常奇怪的语法。它的性能如何?【参考方案12】:

在您的 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);  

【讨论】:

【参考方案13】:

在 MonoDroid / Xamarin.Android 中你可以这样做:

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

但由于在 Android 中不推荐使用 GetIdentifier - 您可以像这样使用反射:

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

我建议在其中放置一个 try/catch 或验证您传递的字符串。

【讨论】:

【参考方案14】:

为了从 String 资源名称获取 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;
    

【讨论】:

以上是关于Android,从字符串中获取资源ID?的主要内容,如果未能解决你的问题,请参考以下文章

android - 从库中获取资源ID

Android 用字符串资源名称获取int型资源id的几种方式

Android:android.content.res.Resources$NotFoundException:字符串资源 ID #0x5

android.content.res.Resources$NotFoundException: Main 中的字符串资源 ID 致命异常

如何从 android 包中的资源 id 获取 Drawable 对象?

Android:如何在build.gradle中获取资源字符串以支持多种语言的多种口味?