¿Puede el directorio dibujable de Android contener subdirectorios?


497

En la documentación del SDK de Android, todos los ejemplos utilizados con la sintaxis @ drawable / my_image xml abordan directamente las imágenes que se almacenan en el directorio res / drawable de mi proyecto.

Me pregunto si explícitamente no está bien crear un subdirectorio dentro del directorio dibujable.

Por ejemplo, si tuviera el siguiente diseño de directorio:

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

¿Podría hacer referencia a la imagen de un sándwich de ensalada de atún como @ drawable / sandwiches / tunaOnRye

¿O tengo que mantener la jerarquía plana en el directorio dibujable?


16
Tenga en cuenta que las mayúsculas no están permitidas en el directorio res.
Tyler

1
Solo puede hacer esto con Gradle: stackoverflow.com/a/19859379
Yair Kukielka

2
¿Es posible tener directorios SIBLING a dibujables , con la funcionalidad dibujable? Entonces, res / tanks / drawble- [hdpi .. etc] y así sucesivamente?
Fattie

Respuestas:


546

No, el mecanismo de recursos no admite subcarpetas en el directorio dibujable, por lo que sí, debe mantener esa jerarquía plana.

El diseño del directorio que mostró no resultaría en ninguna de las imágenes disponibles.

Según mis propios experimentos, parece que tener una subcarpeta con cualquier elemento dentro de la res/drawablecarpeta hará que el compilador de recursos falle, evitando que el R.javaarchivo se genere correctamente.


136
A partir de Android 2.2, esto no causa un error de compilación, pero cualquier subdirectorio se ignora al generar la clase R. Esto realmente apesta y hace que sea difícil administrar proyectos más grandes. = /
Nik Reiman

70
Totalmente de acuerdo. Necesitan encontrar una mejor solución que soporte subcarpetas. No puede ser tan difícil.
znq

13
Espero que esto se resuelva pronto, tengo más de 100 activos, e incluso entonces eliminé algunos de ellos. Yegua nocturna total tratando de gestionar cualquier proyecto marginalmente complejo.
Emile

14
Este es el problema correspondiente en el rastreador de problemas de Android: code.google.com/p/android/issues/detail?id=2018
espinchi

44
maldito tú android
whitneyland

149

La solución alternativa que estoy usando (y la que Android parece favorecer) es esencialmente sustituir un guión bajo por una barra diagonal, para que su estructura se vea así:

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

El enfoque requiere que sea meticuloso al nombrar y no hace que sea mucho más fácil manipular los archivos ellos mismos (si decidiera que las bebidas y los sándwiches realmente deberían ser " food", tendría que hacer un cambio de nombre masivo en lugar de simplemente moviéndolos al directorio); pero la complejidad de su lógica de programación no sufre demasiado en comparación con la estructura de carpetas equivalente.

Esta situación apesta de hecho. Android es una mezcla de decisiones de diseño maravillosas y terribles. Solo podemos esperar que la última porción sea eliminada con toda prisa :)


31
Solo una nota de que no se permiten letras mayúsculas en la carpeta dibujable. Me sale el error: "Nombre de archivo no válido: debe contener solo [a-z0-9_.]"
Jason Axelson

55
+1 por "mezcla de decisiones de diseño maravillosas y terribles"
Brent Faust

1
Apenas una solución: más bien "lo que debe hacer para no volverse completamente loco". Es ridículo estar limitado a un directorio.
RichieHH

35

En realidad, en Android Studio es posible. Puede tener recursos anidados como se muestra aquí :

ingrese la descripción de la imagen aquí

También hay un complemento para agrupar recursos aquí .


Hola, desarrollador @android! Intenté agregar esto al archivo build.gradle: sourceSets {main {res {srcDir 'src / main / res / drawable / ic-toggle'}}}, pero tengo "Uri no está registrado" para xmlns : android = " schemas.android.com/apk/res/android . ¿Cuál podría ser el caso?
AlexKost

@AlexKost Realmente intenté esto solo una vez. No tengo suficiente experiencia para ayudarlo. Lo siento.
Desarrollador de Android

@RahulMandaliya Aunque es posible, sugiero no usarlo.
Desarrollador de Android

@androiddeveloper ¿Por qué no?
Josh Hansen

1
@JoshHansen Es desordenado.
Desarrollador de Android el

34

Sí, apesta :) Sin embargo, puede usar la carpeta de activos y tener subdirectorios allí y cargar imágenes de esa manera.


66
el problema no es solo para la carpeta dibujable sino también para la carpeta de diseño :( La carpeta de mi diseño contiene más de 100 archivos xml, y es difícil para mí abrir el diseño xml correcto en esto.
anticafe

Aparte de otras objeciones, los recursos pueden localizarse fácilmente, pero AFAIK no existe un mecanismo integrado para los activos.
Fran Marzoa

@anticafe use "Ir al recurso" en su IDE (Eclipse: CTRL + SHIFT + R, IDEA / Android Studio: CTRL + SHIFT + N)
TWiStErRob

23

Use la carpeta de activos.

Código de muestra:

InputStream is = null;
try {
    is = this.getResources().getAssets().open("test/sample.png");
} catch (IOException e) {
    ;
}

image = BitmapFactory.decodeStream(is);

55
El único problema con este método es que hay MUCHA más tarea relacionada con el uso de mapas de bits. El sistema de recursos de Android hace un trabajo mucho mejor de administración de memoria. ¿Por qué reconstruirías un sistema de administración de memoria cuando Android ya lo hace? Espeicalmente, si tiene más de 100 imágenes, es mucha carga y liberación de mapas de bits.
Rev Tyler

18
Este es un problema real si planea localizar su aplicación, también si tiene diferentes recursos para diferentes densidades de pantalla, por lo que no es una solución, solo una solución válida solo para algunos casos.
Fran Marzoa

1
Necesito dar el comentario de @Fran al menos mil votos a favor :)
HGPB

22

Escribí un complemento de eclipse que permite crear una subcarpeta virtual separando el nombre del archivo con dos guiones bajos __. El proyecto se encuentra en las primeras etapas, pero no se preocupe, no bloqueará su IDE.

Puede encontrar más detalles aquí, no dude en bifurcar y enviar solicitudes de extracción:

https://github.com/kirill578/Android-Sorted-Res-Folder

ingrese la descripción de la imagen aquí


2
¡Agradable! ¿Alguna posibilidad de portar esto a Android Studio también?
BVB

1
Actualmente ni siquiera estoy usando Android Studio, así que supongo que tendremos que esperar a que algunos experimentados lo porten.
Kirill Kulakov

9

Me gusta usar una secuencia de comandos simple para aplanar una estructura de directorio organizada proporcionada por los diseñadores a algo que pueda usarse para generar un archivo R.

Ejecutar con la ruta actual en drawable-hdpi:

#! /bin/bash
DIRS=`find * -type d`
for dir in ${DIRS} ; do 
  for file in `ls ${dir}` ; do
    mv ${dir}/${file}  ${dir}_${file};
  done 
  rmdir ${dir};
done

1
Su script no funcionará si hay subcarpetas debajo de las carpetas. Creo que necesita reemplazar todo '/' con '_' en $ {dir}.
Seunghoon

9

En Android Studio con Gradle, puede tener múltiples directores de origen que le permitirán separar los recursos. Por ejemplo:

android {
    ....
    android.sourceSets {
        main.res.srcDirs = ['src/main/extraresdirnamed_sandwiches', 'src/main/res']
    }
    ....
}

Sin embargo, los nombres no deben colisionar, lo que significa que aún necesitará tener nombres como sandwiches_tunaOnRye, pero podrá tener una sección separada para todos sus sándwiches.

Esto le permite almacenar sus recursos en diferentes estructuras (útil para contenido generado automáticamente como actionbargenerator)


4

Una forma de solucionar parcialmente el problema es utilizar el sufijo de nivel API. Yo uso res / layout-v1, res / layout-v2, etc. para mantener múltiples subproyectos en el mismo apk. Este mecanismo se puede usar para todos los tipos de recursos.

Obviamente, esto solo se puede usar si está apuntando a niveles de API por encima de res / layout-v? Tu estas usando.

Además, ten cuidado con el error en Android 1.5 y 1.6. Consulte la documentación de Andoroid sobre el sufijo de nivel API .


A quien rebajó esta respuesta: ¿Puedes explicar por qué? Este mecanismo, aunque no es bonito, funciona bien para mí.
OferR

4

Con la llegada del sistema de bibliotecas, la creación de una biblioteca por gran conjunto de activos podría ser una solución.

Todavía es problemático ya que uno debe evitar usar los mismos nombres dentro de todos los activos, pero usar un esquema de prefijo por biblioteca debería ayudar con eso.

No es tan simple como poder crear carpetas, pero eso ayuda a mantener la cordura ...


Sí, creo que esto es bueno. Si agrego banderas de países a mis carpetas de drawable-ldpi, etc., se inundarán. Creo que crear un proyecto de biblioteca para todos los recursos genéricos ayudará a reducir el desorden en el proyecto en el que está trabajando activamente. Sorprendido, solo tienes 1 voto a favor.
Tom

3

Hay una solución para esta situación: puede crear una resVectorcarpeta (por ejemplo) en el mismo nivel que la rescarpeta predeterminada . Allí puede agregar cualquier drawable-xxxcarpeta de recursos allí:

resVector
-drawable
-layout
-color

Después de eso, todo lo que necesitas es agregar

sourceSets {
        main.res.srcDirs += 'src/main/resVector'
    }

en su build.gradlearchivo (dentro android { }).


Lamentablemente, se fusionan en el panel del proyecto en Android Studio cuando se usa la perspectiva "Android" :(
AjahnCharles

@AjahnCharles: prefiero no usar esta perspectiva (de todos modos, siempre estoy trabajando en el 'modo libre de distracciones') ... Pero tienes razón: "Android" combina todo.
Anton Derevyanko el

1

Este no es un método perfecto. Debe implementar la misma forma que se muestra aquí .

También puede llamar a la imagen debajo de la carpeta a través del código que puede usar

Resources res = getResources();
Drawable shape = res. getDrawable(R.drawable.gradient_box);

TextView tv = (TextView)findViewByID(R.id.textview);
tv.setBackground(shape);


1

Gradle con Android Studio podría hacerlo de esta manera ( enlace ).

Está en el párrafo "Configuración de la estructura"

sourceSets {
 main {
    java {
        srcDir 'src/java'
    }
    resources {
        srcDir 'src/resources'
    }
 }
}

1

crear una carpeta en main como: 'res_notification_btn'

y crea una carpeta de árbol en.

luego en 'build.gradle' agregue esto

sourceSets
            {
                main
                {
                    res
                    {
                        srcDirs = ['src/main/res_notification_btn', 'src/main/res']
                      or
                        srcDir 'src/main/res_notification_btn'
                    }
                }
            }

0
#!/usr/bin/env ruby

# current dir should be drawable-hdpi/ etc

# nuke all symlinks
Dir.foreach('.') {|f|
    File.delete(f) if File.symlink?(f)
}

# symlink all resources renaming with underscores
Dir.glob("**/*.png") {|f|
    system "ln -s #{f} #{f.gsub('/', '_')}" if f.include?("/")
}

Todo lo que hace es automatizar la solución sugerida por Cheezmeister. Me está funcionando ... ¿te importaría explicar el voto negativo?
Blake Miller


0

activos / Puede usarlo para almacenar archivos de activos sin procesar. Los archivos que guarde aquí se compilan en un archivo .apk tal cual y se conserva el nombre de archivo original. Puede navegar por este directorio de la misma manera que un sistema de archivos típico usando URI y leer archivos como una secuencia de bytes usando el AssetManager. Por ejemplo, esta es una buena ubicación para texturas y datos de juegos. http://developer.android.com/tools/projects/index.html


0

Los subdirectorios no están permitidos, el recurso debe contener solo [a-z0-9_.].

No, tienes letras mayúsculas y no hay barras diagonales.


-3
  1. Haga clic derecho en Drawable
  2. Seleccione Nuevo ---> Directorio
  3. Ingrese el nombre del directorio. Por ejemplo: logo.png (la ubicación ya mostrará la carpeta dibujable por defecto)
  4. Copie y pegue las imágenes directamente en la carpeta dibujable. Al pegar, tiene la opción de elegir mdpi / xhdpi / xxhdpi, etc. para cada una de las imágenes de una lista. Seleccione la opción apropiada e ingrese el nombre de la imagen. Asegúrese de mantener el mismo nombre que el nombre del directorio, es decir, logo.png
  5. Haga lo mismo para las imágenes restantes. Todos ellos se colocarán debajo de la carpeta principal logo.png.
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.