Android 从 Resources 对象中检索所有 Drawable 资源

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/3221603/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-20 09:13:06  来源:igfitidea点击:

Retrieving all Drawable resources from Resources object

androidcollectionsresourcesdrawable

提问by Matt Huggins

In my Android project, I want to loop through the entire collection of Drawableresources. Normally, you can only retrieve a specific resource via its ID using something like:

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

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

However, I want to get all Drawableresources where I won'tknow their ID's beforehand. Is there a collection I can loop through or perhaps a way to get the list of resource ID's given the resources in my project?

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

Or, is there a way for me in Java to extract all property values from the R.drawablestatic class?

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

采纳答案by adamp

If you find yourself wanting to do this you're probably misusing the resource system. Take a look at assets and AssetManagerif you want to iterate over files included in your .apk.

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

回答by Matt Huggins

Okay, this feels a bit hack-ish, but this is what I came up with via Reflection. (Note that resourcesis an instance of class android.content.res.Resources.)

好吧,这感觉有点hack-ish,但这是我通过反射想出来的。(请注意,这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 */
}

If anyone has a better solution that makes better use of Android calls I might not be aware of, I'd definitely like to see them!

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

回答by Jan-Terje S?rensen

I have taken Matt Huggins great answer and refactored it to make it more generic:

我已经采纳了 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 */
    }   
}

Usage:

用法:

loadDrawables(R.drawable.class);

回答by mishkin

i used getResources().getIdentifier to scan through sequentially named images in my resource folders. to be on a safe side, I decided to cache image ids when activity is created first time:

我使用 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();
}

回答by Mika?l Mayer

Add a picture named aaaa and another named zzzz, then iterate through the following:

添加一个名为 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
  }
}

This worked for me.

这对我有用。

回答by D.Snap

You should use the Raw folder and AssetManager, but if you want to use drawables because why not, here is how...

您应该使用 Raw 文件夹和 AssetManager,但如果您想使用可绘制对象,因为为什么不,这里是如何...

Let's suppose we have a very long file list of JPG drawables and we want to get all the resource ids without the pain of retrieving one by one (R.drawable.pic1, R.drawable.pic2, ... etc)

假设我们有一个很长的 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
}

回答by Macarse

I guess the reflection code will work but I don't understand why you need this.

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

Resources in Android are static once the application is installed so you can have a list of resources or an array. Something like:

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

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

And from your Activityyou can get it by doing:

从你的Activity,你可以通过做得到它:

getResources().getStringArray(R.array.drawables_list);

回答by Alecs

Just do this:

只需这样做:

Field[] declaredFields = (R.drawable.class).getDeclaredFields();

回答by JohnnyLambada

The OP wanted drawables and I needed layouts. This is what I came up with for layouts. The name.startsWithbusiness lets me ignore system generated layouts, so you may need to tweak that a bit. This should work for any resource type by modifying the value of clz.

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

回答by JohnnyLambada

USE THIS MY CODE

使用这个我的代码

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