¿Puede la carpeta Android Layout contener subcarpetas?

En este momento, estoy almacenando cada archivo de diseño xml dentro de la carpeta res/layout , por lo que es posible y simple administrar proyectos pequeños, pero cuando hay un caso de proyectos grandes y pesados, entonces debe haber una jerarquía y carpetas necesarias dentro de la carpeta de diseño.

por ejemplo

 layout -- layout_personal -- personal_detail.xml -- personal_other.xml --layout_address -- address1.xml -- address2.xml 

Del mismo modo, nos gustaría tener subcarpetas para la aplicación grande, ¿hay alguna manera de hacerlo dentro del proyecto de Android?

Puedo crear subcarpetas layout-personal y layout_address dentro de la carpeta de diseño, pero cuando llega el momento de acceder al archivo de diseño xml con R.layout ._______, en ese momento no hay ningún pop-up de diseño xml dentro del menú.

PUEDES hacer esto con gradle. He hecho un proyecto de demostración que muestra cómo.

El truco consiste en utilizar la capacidad de gradle para fusionar varias carpetas de recursos y establecer la carpeta res así como las subcarpetas anidadas en el bloque sourceSets.

La peculiaridad es que no puede declarar una carpeta de recursos de contenedor antes de declarar las carpetas de recursos secundarios de esa carpeta.

A continuación se muestra el bloque de sourceSets del archivo build.gradle de la demostración. Tenga en cuenta que las subcarpetas se declaran primero.

 sourceSets { main { res.srcDirs = [ 'src/main/res/layouts/layouts_category2', 'src/main/res/layouts', 'src/main/res' ] } } 

imagen de recursos anidados

Además, el padre directo de sus archivos de recursos reales (pngs, diseños xml, etc.) todavía necesita corresponderse con la especificación .

La respuesta es no.

Me gustaría llamar su atención hacia este libro Pro Android 2 que dice:

También vale la pena señalar algunas limitaciones con respecto a los recursos. En primer lugar, Android solo admite una lista lineal de archivos dentro de las carpetas predefinidas en res. Por ejemplo, no admite carpetas anidadas en la carpeta de diseño (o las otras carpetas en res).

En segundo lugar, hay algunas similitudes entre la carpeta de activos y la carpeta sin formato bajo res. Ambas carpetas pueden contener archivos sin procesar, pero los archivos sin procesar se consideran recursos y los archivos dentro de los activos no lo son.

Tenga en cuenta que debido a que los contenidos de la carpeta de activos no se consideran recursos, puede colocar una jerarquía arbitraria de carpetas y archivos dentro de ella.

Solo quería agregar a la fantástica respuesta de eskis para las personas que tienen problemas. (Nota: esto solo funcionará y se verá como directorios separados dentro de la vista ‘proyecto’, no desafortunadamente la vista ‘Android’).

Probado con lo siguiente. BuildToolsVersion = 23.0.0 gradle 1.2.3 y 1.3.0

Así es como conseguí que el mío funcionara con un proyecto ya construido.

  1. Copie todos los archivos XML de su directorio de diseño y colóquelos en un directorio en el escritorio o algo para hacer una copia de seguridad.
  2. Elimine todo el directorio de diseño (¡Asegúrese de hacer una copia de seguridad de todo desde el paso 1!)
  3. Haga clic derecho en el directorio res y seleccione nuevo> directorio.
  4. Nombre este nuevo directorio “diseños”. (Esto puede ser lo que quieras, pero no será un directorio de ‘fragmento’ o ‘actividad’, que viene después).
  5. Haga clic con el botón derecho en el nuevo directorio “diseños” y seleccione nuevo> directorio. (Este será el nombre del tipo de archivos XML que tendrá en él, por ejemplo, ‘fragmentos’ y ‘actividades’).
  6. Haga clic derecho en el directorio ‘fragmento’ o ‘actividades’ (Nota: esto no tiene que ser ‘fragmento’ o ‘actividades’ que es lo que estoy usando como ejemplo) y seleccione nuevo> directorio una vez más y nombre este directorio “diseño”. (Nota: ¡DEBE llamarse ‘diseño’ !!! muy importante).
  7. Coloque los archivos XML que desee dentro del nuevo directorio de “diseño” a partir de la copia de seguridad que realizó en su escritorio.
  8. Repita los pasos 5 a 7 para tantos directorios personalizados como desee.
  9. Una vez que esto esté completo, ingrese en su archivo gradle.build de módulos y cree una definición de sourceSets como esta … (¡Asegúrese de que ‘src / main / res / layouts’ y ‘src / main / res’ sean siempre los dos inferiores! !! Como lo estoy mostrando a continuación).

     sourceSets { main { res.srcDirs = [ 'src/main/res/layouts/activities', 'src/main/res/layouts/fragments', 'src/main/res/layouts/content', 'src/main/res/layouts', 'src/main/res' ] } } 
  10. Beneficio $$$$

Pero en serio … así es como lo hice funcionar. Avíseme si alguien tiene alguna pregunta. Puedo intentar ayudar.

Las imágenes valen más que las palabras.

Estructura de directorios

No es posible, pero la carpeta de diseño está ordenada por nombre. Por lo tanto, antepongo los nombres de archivo de disposición con mis nombres de paquete. Por ejemplo, para los dos paquetes “comprar” y “jugar”:

 buying_bought_tracks.xml buying_buy_tracks.xml playing_edit_playlist.xml playing_play_playlist.xml playing_show_playlists.xml 

Ahora con Android Studio y Gradle, puede tener múltiples carpetas de recursos en su proyecto. Permitiendo organizar no solo sus archivos de diseño sino también cualquier tipo de recursos.

No es exactamente una subcarpeta, pero puede separar partes de su aplicación.

La configuración es así:

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

Verifique la documentación .

Utilizo el plugin de Android File Grouping para Android Studio. Realmente no le permite crear subcarpetas, pero puede mostrar sus archivos y recursos, ya que están en diferentes carpetas. Y esto es exactamente lo que quería.

Puede instalar el complemento “Agrupación de archivos de Android” por

Windows:

Android Studio -> Archivo -> Configuración -> Complementos.

Mac:

Android Studio -> Android Studio Tab (arriba a la izquierda) -> Preferencias -> Complementos -> Instalar JetBrains Plugin …

Para Mac, pude probarlo y no pude buscar el complemento. Así que descargué el complemento desde aquí y utilicé la opción Install plugin from disk desde la configuración anterior.

Creo que la solución más elegante para este problema (dado que las subcarpetas no están permitidas) es anteponer los nombres de los archivos con el nombre de la carpeta en la que lo habría colocado. Por ejemplo, si tiene un conjunto de diseños para una Actividad, Fragmento o simplemente una vista general llamada “lugares”, debería simplemente anteponerlo a places_my_layout_name. Al menos, esto resuelve el problema de organizarlos de una manera que sean más fáciles de encontrar dentro del IDE. No es la solución más increíble, pero es mejor que nada.

Pequeño problema

Puedo lograr subcarpetas al seguir la respuesta principal a esta pregunta.

Sin embargo, a medida que el proyecto crezca, tendrá muchas subcarpetas:

 sourceSets { main { res.srcDirs = [ 'src/main/res/layouts/somethingA', 'src/main/res/layouts/somethingB', 'src/main/res/layouts/somethingC', 'src/main/res/layouts/somethingD', 'src/main/res/layouts/somethingE', 'src/main/res/layouts/somethingF', 'src/main/res/layouts/somethingG', 'src/main/res/layouts/somethingH', 'src/main/res/layouts/...many more', 'src/main/res' ] } } 

No es un gran problema, pero:

  • no es bonito ya que la lista se vuelve muy larga.
  • debe cambiar su app/build.gradle cada vez que agrega una nueva carpeta.

Mejora

Así que escribí un método simple Groovy para tomar todas las carpetas anidadas:

 def getLayoutList(path) { File file = new File(path) def throwAway = file.path.split("/")[0] def newPath = file.path.substring(throwAway.length() + 1) def array = file.list().collect { "${newPath}/${it}" } array.push("src/main/res"); return array } 

Pegue este método fuera del bloque de android {...} en su app/build.gradle .


Cómo utilizar

Para una estructura como esta:

  ├── app <---------- TAKE NOTE ├── build ├── build.gradle ├── gradle ├── gradle.properties ├── gradlew ├── gradlew.bat ├── local.properties └── settings.gradle 

Úselo así:

 android { sourceSets { main { res.srcDirs = getLayoutList("app/src/main/res/layouts/") } } } 

Si tienes una estructura como esta:

  ├── my_special_app_name <---------- TAKE NOTE ├── build ├── build.gradle ├── gradle ├── gradle.properties ├── gradlew ├── gradlew.bat ├── local.properties └── settings.gradle 

Lo usarás así:

 android { sourceSets { main { res.srcDirs = getLayoutList("my_special_app_name/src/main/res/layouts/") } } } 

Explicación

getLayoutList() toma a relative path como argumento. La relative path es relativa a la raíz del proyecto. Entonces, cuando ingresamos "app/src/main/res/layouts/" , devolverá el nombre de todas las subcarpetas como una matriz, que será exactamente igual a:

  [ 'src/main/res/layouts/somethingA', 'src/main/res/layouts/somethingB', 'src/main/res/layouts/somethingC', 'src/main/res/layouts/somethingD', 'src/main/res/layouts/somethingE', 'src/main/res/layouts/somethingF', 'src/main/res/layouts/somethingG', 'src/main/res/layouts/somethingH', 'src/main/res/layouts/...many more', 'src/main/res' ] 

Aquí está el guión con comentarios para entender:

 def getLayoutList(path) { // let's say path = "app/src/main/res/layouts/ File file = new File(path) def throwAway = file.path.split("/")[0] // throwAway = 'app' def newPath = file.path.substring(throwAway.length() + 1) // +1 is for '/' // newPath = src/main/res/layouts/ def array = file.list().collect { // println "filename: ${it}" // uncomment for debugging "${newPath}/${it}" } array.push("src/main/res"); // println "result: ${array}" // uncomment for debugging return array } 

¡Espero eso ayude!

Ahora podemos hacer fácilmente con el complemento JetBrains llamado ” Agrupación de archivos de Android

mira este enlace

Agrupación de archivos de Android

enter image description here

Comprobar secuencia de comandos Bash Flatten Folder que convierte la jerarquía de carpetas en una sola carpeta

Una forma de hacerlo fue crear una carpeta de res separada en el mismo nivel que la carpeta de res real en tu proyecto, luego puedes usar esto en tus aplicaciones build.gradle

 android { //other stuff sourceSets { main.res.srcDirs = ['src/main/res', file('src/main/layouts').listFiles()] } } 

estructura de carpeta de ejemplo

entonces cada subcarpeta de su nueva carpeta de res puede ser algo relacionado con cada pantalla en particular o algo de su aplicación, y cada carpeta tendrá su propio layout / drawable / values etc., manteniendo las cosas organizadas y no tendrá que actualizar el archivo gradle manualmente como algunos de estas otras respuestas requieren (simplemente sincronice su gradle cada vez que agregue una nueva carpeta de recursos para que lo sepa, y asegúrese de agregar las subcarpetas relevantes antes de agregar sus archivos xml).

Si está desarrollando en un linux o en un mac box, una solución alternativa sería crear subcarpetas que incluyan enlaces simbólicos a sus archivos de diseño. Simplemente use el comando ln con -s

ln -s PATH_TO_YOUR_FILE

El problema con esto es que su carpeta de diseño todavía contiene todos los archivos .xml. Pero podría aunque los seleccione al usar las subcarpetas. Es lo más parecido a lo que te gustaría tener.

Acabo de leer que esto también podría funcionar con Windows si usa Vista o posterior. Hay este comando mklink . Solo busca en google, nunca lo he usado.

Otro problema es que si tiene el archivo abierto e intenta abrirlo de nuevo, el complemento arroja una excepción de puntero NULL. Pero no cuelga.

Si bien todas las propuestas de conjuntos de recursos múltiples pueden funcionar, el problema es que la lógica actual para el complemento de Android Studio Gradle no actualizará los archivos de recursos después de que hayan cambiado para conjuntos de recursos nesteds. La implementación actual intenta verificar los directorios de recursos usando startsWith (), por lo que una estructura de directorio que está anidada (es decir, src / main / res / layout / layouts y src / main / res / layout / layouts_category2) elegirá src / main / res / layout / layouts consistentemente y nunca actualiza los cambios. El resultado final es que debe reconstruir / limpiar el proyecto cada vez.

Envié un parche a https://android-review.googlesource.com/#/c/157971/ para tratar de ayudar a resolver las cosas.

La respuesta principal de @eski es buena, pero el código no es elegante de usar, así que escribí un guión maravilloso en Gradle para uso general. Se aplica a todos los tipos de comstackción y al sabor del producto, y no solo se puede usar para el diseño, sino que también se puede agregar una subcarpeta para cualquier otro tipo de recursos, como drawable. Aquí está el código (colóquelo en el bloque android del archivo gradle de nivel de proyecto):

 sourceSets.each { def rootResDir = it.res.srcDirs[0] def getSubDirs = { dirName -> def layoutsDir = new File(rootResDir, dirName) def subLayoutDirs = [] if (layoutsDir.exists()) { layoutsDir.eachDir { subLayoutDirs.add it } } return subLayoutDirs } def resDirs = [ "anims", "colors", "drawables", "drawables-hdpi", "drawables-mdpi", "drawables-xhdpi", "drawables-xxhdpi", "layouts", "valuess", ] def srcDirs = resDirs.collect { getSubDirs(it) } it.res.srcDirs = [srcDirs, rootResDir] } 

¿Cómo hacer en la práctica?

Por ejemplo, quiero crear una subcarpeta llamada activity para el layout , agregar una cadena con cualquier nombre en la variable resDirs como layouts , luego el archivo xml del diseño debe colocarse en res\layouts\activity\layout\xxx.xml .

Si quiero crear una subcarpeta llamada selectors para drawable , agregue una cadena con cualquier nombre en la variable resDirs como, por ejemplo, resDirs , luego el archivo xml dibujable debe colocarse en res\drawables\selectors\drawable\xxx.xml .

El nombre de la carpeta como layouts y drawables se define en la variable resDirs , puede ser cualquier cadena. Todas las subcarpetas creadas por usted, como la activity o los selectors se consideran igual que la carpeta res . Por lo tanto, en la carpeta de selectors , debemos crear una carpeta drawable adicionalmente y colocar archivos xml en una carpeta dibujable, luego de eso gradle puede reconocer los archivos xml como dibujables normalmente.

  • Paso 1: haz clic con el botón derecho en el diseño: muestra en el explorador
  • Paso 2: abra la carpeta de diseño y cree las subcarpetas directamente: layout_1, layout_2 …
  • Paso 3: abrir diseño_1 crear diseño de carpeta (nota: el nombre obligatorio es diseño), abrir carpeta de diseño_2 crear subdirectorio de diseño (nota: el nombre obligatorio es diseño) …
  • Paso 4: copie los archivos xml en los subdirectorios de diseño en layout_1 y layout_2
  • Paso 5: Ejecute el código en buid.grade (aplicación de módulo) y acceda a la sincronización ahora:

 sourceSets { main { res.srcDirs = [ 'src / main / res / layout / layout_1' 'src / main / res / layout / layout_2', 'src / main / res' ] } } 
  • Paso 6: Resumen: todos los pasos anteriores solo ayudarán a agrupar carpetas y mostrar en modo ‘proyecto’, mientras que el modo ‘Android’ se mostrará de forma normal.
  • Así que dibujo que tal vez nombrar prefijos es tan efectivo como agrupar carpetas.

Si usa el método en la respuesta aprobada y desea mejorarlo un poco, modifique la configuración de Gradle de la siguiente manera:

  sourceSets { main { res.srcDirs = [ file("src/main/res/layouts/").listFiles(), "src/main/res/layouts", "src/main/res" ] } } 

Entonces, si agrega más carpetas y diseños, no necesita volver aquí y anexar una larga lista de carpetas de origen, deje que gradle obtenga todas las carpetas por usted.

Bueno, la respuesta corta es no. Pero definitivamente puedes tener múltiples carpetas de res . Eso, creo, es lo más cercano que se puede llegar a tener subcarpetas para la carpeta de layout . Así es como lo haces.

Las respuestas principales tienen varias desventajas: debe agregar nuevas rutas de diseño, AS coloca recursos nuevos en la carpeta res\layouts lugar de res\values .

Combinando varias respuestas, escribí algo similar:

 sourceSets { main { res.srcDirs = [ 'src/main/res', file("src/main/res/layouts/").listFiles(), 'src/main/res/layouts' ] } } 

Hice carpetas con este artículo: http://alexzh.com/tutorials/how-to-store-layouts-in-different-folders-in-android-project/ . Para crear subcarpetas, debe usar este menú: Nuevo> Carpeta> Carpeta Res.

ACTUALIZAR

Después de un par de semanas, descubrí que Android Studio no nota los cambios en los recursos . Entonces, aparecen algunos errores extraños. Por ejemplo, los diseños siguen mostrando tamaños y márgenes antiguos. A veces, AS no encuentra nuevos archivos XML (especialmente durante el tiempo de ejecución). Algunas veces mezcla view id (referencias a otro archivo XML). A menudo se requiere presionar Build > Clean Project o Build > Rebuild Project . Se requiere Read Rebuild después de cambiar los archivos de diseño xml en Android Studio .