1

I have a lot images in drawable that I wish to put into an array. Putting them into an array manually will just take too long, both in time and code. I was wondering if there is a way to loop through R.drawable, something like this:

ArrayList<Integer> imgArr = new ArrayList<>();
for(int k=0; k<R.drawable.size(); k++) {
    imgArr.add(R.drawable.get(k));
}
Henry Twist
  • 5,666
  • 3
  • 19
  • 44
  • "*Putting them into an array manually will just take too long, both in time and code.*" How is putting them in an `ArrayList` faster? – Wais Kamal Jun 18 '21 at 08:22
  • I see I didn't make myself clear. I meant like instead of typing out all the file names into an array OR arraylist, is there a way to loop through the R.drawable without having to specify the image file name. – GlennTheAlien Jun 18 '21 at 08:32
  • I don't think that's how resources are supposed to work. Maybe using the assets folder would better suit you? See: https://stackoverflow.com/a/3224478/12622119 – Quadslab Jun 18 '21 at 12:23
  • Does this answer your question? [Retrieving all Drawable resources from Resources object](https://stackoverflow.com/questions/3221603/retrieving-all-drawable-resources-from-resources-object) – Quadslab Jun 18 '21 at 12:24

1 Answers1

1

First of all you should probably understand the R class a bit: Read more here

In short: the R class is a dynamically generated class which contains inner classes (such as the drawable class). These inner classes contain multiple Integer constants, which are linked to the corresponding resource

This means that, since the drawables here are defined as members of the R.drawable class we need to use reflection to access them all. First we need to get hold of an instance of the drawable subclass. Unfortunately the constructor of this class is private, but we can get around this using a bit more reflection:

Class<R.drawable> drawableClass = R.drawable.class;
R.drawable instance = (R.drawable) drawableClass.getConstructors()[0].newInstance();

Next we create an ArrayList and for each of the Fields which are declared in the R.drawable class we get the value which are set in our instance (since they are constants those will be the correct values) and add it to the list:

List<Integer> drawables = new ArrayList<>();
for (Field field :
    drawableClass.getDeclaredFields()) {
    int value = field.getInt(instance);
    drawables.add(value);
}

Which already completes all the code needed, you can now use the Integers in the list normally, as if you were using R.drawable.icon. Note however, that getDeclaredConstructors(), newInstance(), getDeclaredFields() and getInt() all throw Exceptions, which need to be caught.

Full Snippet (Java):

public static List<Integer> getDrawablesList() throws IllegalAccessException, InvocationTargetException, InstantiationException {
    Class<R.drawable> drawableClass = R.drawable.class;
    R.drawable instance = (R.drawable) drawableClass.getDeclaredConstructors()[0].newInstance();
    List<Integer> drawables = new ArrayList<>();
    for (Field field :
            drawableClass.getDeclaredFields()) {
        int value = field.getInt(instance);
        drawables.add(value);
    }
    return drawables;
}

Full Snippet (Kotlin):

(requires the "org.jetbrains.kotlin:kotlin-reflect:YOUR_KOTLIN_VERSION" dependency)

private fun getDrawablesList() : List<Int> {
    val drawableClass = R.drawable::class
    val instance = drawableClass.constructors.first().call()
    val drawablesList = mutableListOf<Int>()
    for (field in instance.javaClass.declaredFields) {
        val test = field.getInt(instance)
        drawablesList.add(test)
    }
    return drawablesList
}
Tommyten
  • 21
  • 1
  • 4
  • Ohhh that makes a lot sense, wow. Thank you so much for the great explanation!! – GlennTheAlien Jun 18 '21 at 12:35
  • I was used this method to list all the drawables on my app but now, on Android 11 (Api 30) seems not work anymore, maybe is because the new api don't allow the utilization of reflection. – Talu Aug 05 '21 at 05:55