¿Puede la carpeta Android Layout contener subcarpetas?


Answers

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.

Question

En este momento, estoy almacenando cada archivo de diseño xml dentro de la carpeta res/layout , por lo que es factible y simple administrar proyectos pequeños, pero cuando hay un caso de proyectos grandes y pesados, entonces debe haber una jerarquía y una subcategoría. 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ú.




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 here y utilicé la opción Install plugin from disk desde la configuración anterior.




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



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 compilació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.




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

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.







  • 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.



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:

<project root>
├── 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:

<project root>
├── 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!




Related