25

在我的 Android 项目中,我想遍历整个Drawable资源集合。通常,您只能使用以下方式通过其 ID 检索特定资源:

InputStream is = Resources.getSystem().openRawResource(resourceId)

但是,我想获得所有Drawable我事先不知道他们的 ID 的资源。是否有一个我可以循环的集合,或者是否有一种方法可以获取给定项目中资源的资源 ID 列表?

或者,有没有办法让我在 Java 中从R.drawable静态类中提取所有属性值?

4

11 回答 11

34

好的,这感觉有点 hack-ish,但这是我通过 Reflection 提出的。(请注意,这resources是 class 的一个实例android.content.res.Resources。)

final R.drawable drawableResources = new R.drawable();
final Class<R.drawable> c = R.drawable.class;
final Field[] fields = c.getDeclaredFields();

for (int i = 0, max = fields.length; i < max; i++) {
    final int resourceId;
    try {
        resourceId = fields[i].getInt(drawableResources);
    } catch (Exception e) {
        continue;
    }
    /* make use of resourceId for accessing Drawables here */
}

如果有人有更好的解决方案,可以更好地利用我可能不知道的 Android 调用,我肯定希望看到它们!

于 2010-07-11T03:48:46.723 回答
8

我使用 getResources().getIdentifier 扫描资源文件夹中按顺序命名的图像。为了安全起见,我决定在第一次创建活动时缓存图像 ID:

    private void getImagesIdentifiers() {

    int resID=0;        
    int imgnum=1;
    images = new ArrayList<Integer>();

    do {            
        resID=getResources().getIdentifier("img_"+imgnum, "drawable", "InsertappPackageNameHere");
        if (resID!=0)
            images.add(resID);
        imgnum++;
    }
    while (resID!=0);

    imageMaxNumber=images.size();
}
于 2010-10-16T18:47:19.693 回答
8

我接受了 Matt Huggins 的出色回答,并对其进行了重构以使其更通用:

public static void loadDrawables(Class<?> clz){
    final Field[] fields = clz.getDeclaredFields();
    for (Field field : fields) {
        final int drawableId;
        try {
            drawableId = field.getInt(clz);
        } catch (Exception e) {
            continue;
        }
        /* make use of drawableId for accessing Drawables here */
    }   
}

用法:

loadDrawables(R.drawable.class);
于 2013-03-06T20:39:35.417 回答
7

你应该使用 Raw 文件夹和 AssetManager,但是如果你想使用 drawables,为什么不呢,这里是如何...

假设我们有一个很长的 JPG 可绘制文件列表,并且我们想要获取所有资源 id,而无需一一检索(R.drawable.pic1、R.drawable.pic2 等)

//first we create an array list to hold all the resources ids
ArrayList<Integer> imageListId = new ArrayList<Integer>();

//we iterate through all the items in the drawable folder
Field[] drawables = R.drawable.class.getFields();
for (Field f : drawables) {
    //if the drawable name contains "pic" in the filename...
    if (f.getName().contains("image"))
        imageListId.add(getResources().getIdentifier(f.getName(), "drawable", getPackageName()));
}

//now the ArrayList "imageListId" holds all ours image resource ids
for (int imgResourceId : imageListId) {
     //do whatever you want here
}
于 2017-03-17T11:38:51.043 回答
6

添加一个名为 aaaa 的图片和另一个名为 zzzz 的图片,然后遍历以下内容:

public static void loadDrawables() {
  for(long identifier = (R.drawable.aaaa + 1);
      identifier <= (R.drawable.zzzz - 1);
      identifier++) {
    String name = getResources().getResourceEntryName(identifier);
    //name is the file name without the extension, indentifier is the resource ID
  }
}

这对我有用。

于 2013-10-02T07:04:41.340 回答
4

如果您发现自己想要这样做,您可能误用了资源系统。查看资产,AssetManager如果您想遍历 .apk 中包含的文件。

于 2010-07-11T20:14:32.917 回答
3

我想反射代码会起作用,但我不明白你为什么需要这个。

一旦安装了应用程序,Android 中的资源就是静态的,因此您可以拥有资源列表或数组。就像是:

<string-array name="drawables_list">
    <item>drawable1</item>
    <item>drawable2</item>
    <item>drawable3</item>
</string-array>

从你Activity那里你可以得到它:

getResources().getStringArray(R.array.drawables_list);
于 2010-07-11T13:20:11.440 回答
2

只需这样做:

Field[] declaredFields = (R.drawable.class).getDeclaredFields();
于 2015-11-02T14:53:33.797 回答
0

OP 想要可绘制对象,而我需要布局。这就是我想出的布局。业务让我忽略系统生成的name.startsWith布局,因此您可能需要稍微调整一下。通过修改 的值,这应该适用于任何资源类型clz

public static Map<String,Integer> loadLayouts(){
    final Class<?> clz = R.layout.class;
    Map<String,Integer> layouts = new HashMap<>();
    final Field[] fields = clz.getDeclaredFields();
    for (Field field : fields) {
        String name = field.getName();
        if (
                !name.startsWith("abc_")
                && !name.startsWith("design_")
                && !name.startsWith("notification_")
                && !name.startsWith("select_dialog_")
                && !name.startsWith("support_")
        ) {
            try {
                layouts.put(field.getName(), field.getInt(clz));
            } catch (Exception e) {
                continue;
            }
        }
    }
    return layouts;
}
于 2016-04-06T16:33:12.117 回答
0

使用我的代码

R.drawable drawableResources = new R.drawable();
Class<R.drawable> c = R.drawable.class;
Field[] fields = c.getDeclaredFields();

for (int i = 0, max = fields.length; i < max; i++) {
    final int resourceId;
    try {
        resourceId = fields[i].getInt(drawableResources);
        // call save with param of resourceId
        SaveImage(resourceId);
    } catch (Exception e) {
        continue;
    }
}

...

public void SaveImage(int resId){
    if (!CheckExternalStorage()) {
        return;
    }

    Bitmap bmp = BitmapFactory.decodeResource(getResources(), resID);
    try {
        File dir = new File(path);
        if (!dir.exists()) {
            dir.mkdirs();
        }
        OutputStream fOut = null;
        File file = new File(path, "image1.png");
        file.createNewFile();
        fOut = new FileOutputStream(file);
        bmp.compress(Bitmap.CompressFormat.PNG, 100, fOut);
        fOut.flush();
        fOut.close();
        MediaStore.Images.Media.insertImage(this.getContentResolver(), file.getAbsolutePath(), file.getName(), file.getName());
        Log.i(LOGTAG, "Image Written to Exterbal Storage");

    } catch (Exception e) {
        Log.e("saveToExternalStorage()", e.getMessage());
    }
}
于 2017-08-10T13:26:28.167 回答
0

在 Kotlin 中创建一组可绘制对象:

    val drawablesFields: Array<Field> = drawable::class.java.fields
    val drawables: ArrayList<Drawable> = ArrayList()
    for (field in drawablesFields) {
        context?.let { ContextCompat.getDrawable(it, field.getInt(null)) }?.let {
            drawables.add (
                it
            )
        }
    }
于 2020-06-06T09:32:41.707 回答