Can the Android drawable directory contain subdirectories?

Viewed 164217

In the Android SDK documentation, all of the examples used with the @drawable/my_image xml syntax directly address images that are stored in the res/drawable directory in my project.

I am wondering if it is explicitly not okay to create a sub directory within the drawable directory.

For example, if I had the following directory layout:

res/drawable
-- sandwiches
  -- tunaOnRye.png
  -- hamAndSwiss.png
-- drinks
  -- coldOne.png
  -- hotTea.png

Could I reference the image of a tuna salad sandwich as @drawable/sandwiches/tunaOnRye

Or do I have to keep the hierarchy flat in the drawable directory.

22 Answers

No, the resources mechanism doesn't support subfolders in the drawable directory, so yes - you need to keep that hierarchy flat.

The directory layout you showed would result in none of the images being available.

From my own experiments it seems that having a subfolder with any items in it, within the res/drawable folder, will cause the resource compiler to fail -- preventing the R.java file from being generated correctly.

The workaround I'm using (and the one Android itself seems to favor) is to essentially substitute an underscore for a forward slash, so your structure would look something like this:

sandwich_tunaOnRye.png
sandwich_hamAndSwiss.png
drink_coldOne.png
drink_hotTea.png

The approach requires you to be meticulous in your naming and doesn't make it much easier to wrangle the files themselves (if you decided that drinks and sandwiches should really all be "food", you'd have to do a mass rename rather than simply moving them to the directory); but your programming logic's complexity doesn't suffer too badly compared to the folder structure equivalent.

This situation sucks indeed. Android is a mixed bag of wonderful and terrible design decisions. We can only hope for the latter portion to get weeded out with all due haste :)

It is possible to have multiple drawable folders by having an extra folder parallel to 'res' with a subdirectory 'drawable' and then add following to gradle:

sourceSets {
    main {
        res.srcDirs 'src/main/<extra_res>'
    }
}

Tested with gradle 6.5.1

For anyone using Xamarin (either Xamarin.Android or Xamarin.Forms), there is a way to do this.

In the .csproj file for the Android project find the line for MonoAndroidResourcePrefix (documented, though rather poorly, here). Add the subdirectories you are wanting to use here, separating each entry by semicolons. When building, Visual Studio strips these prefixes so that all of the resources end up in a flat hierarchy. You may need to reload the solution after making these changes.

Example of setup in Xamarin

These directories do not need to be subdirectories of the default Resources directory in the project.

Make sure that files you add are getting the build action set to "AndroidResource".

For Xamarin.Android, the visual editor won't recognize images and will show the error "This resource URL cannot be resolved" but the project will build and the image will be visible at runtime.

Error in editor Example in emulator

  1. Right click on Drawable
  2. Select New ---> Directory
  3. Enter the directory name. Eg: logo.png(the location will already show the drawable folder by default)
  4. Copy and paste the images directly into the drawable folder. While pasting you get an option to choose mdpi/xhdpi/xxhdpi etc for each of the images from a list. Select the appropriate option and enter the name of the image. Make sure to keep the same name as the directory name i.e logo.png
  5. Do the same for the remaining images. All of them will be placed under the logo.png main folder.
Related