studio - La cartella Layout di Android può contenere sottocartelle?




relative layout xml android (12)

In questo momento sto memorizzando ogni file di layout xml all'interno della cartella res/layout , quindi è possibile e semplice gestire piccoli progetti, ma quando c'è un caso di progetti grandi e pesanti, allora ci dovrebbe essere una gerarchia e cartelle necessarie all'interno della cartella di layout.

per es

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

Allo stesso modo, vorremmo avere sottocartelle per la grande applicazione, quindi c'è un modo per farlo all'interno del progetto Android?

Sono in grado di creare sottocartelle layout -personale e layout_address all'interno della cartella di layout, ma quando arriva il momento di accedere al file di layout xml usando R.layout ._______, in quel momento non c'è alcun pop-up di layout xml all'interno del menu.


Piccolo problema

Sono in grado di ottenere sottocartelle seguendo la risposta migliore a questa domanda.

Tuttavia, man mano che il progetto si ingrandisce, avrai molte sottocartelle:

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'
            ]
    }
}

Non è un grosso problema, ma:

  • non è carino come la lista diventa molto lunga.
  • devi cambiare app/build.gradle ogni volta che aggiungi una nuova cartella.

Miglioramento

Così ho scritto un semplice metodo Groovy per afferrare tutte le cartelle nidificate:

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
}

Incolla questo metodo al di fuori del blocco di android {...} nella tua app/build.gradle .

Come usare

Per una struttura come questa:

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

Usalo in questo modo:

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

Se hai una struttura come questa:

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

Lo userai in questo modo:

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

Spiegazione

getLayoutList() prende a relative path come argomento. Il relative path è relativo alla radice del progetto. Quindi quando inseriamo "app/src/main/res/layouts/" , restituirà il nome di tutte le sottocartelle come una matrice, che sarà esattamente la stessa di:

            [
                    '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'
            ]

Ecco lo script con commenti per capire:

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
}

Spero che sia d'aiuto!


Bene, la risposta breve è no. Ma sicuramente puoi avere più cartelle di ricerca. Questo, penso, è il più vicino possibile ad avere sottocartelle per la cartella di layout . Here's come lo fai.


La risposta è no.

Vorrei attirare la vostra attenzione su questo libro Pro Android 2 che afferma:

Vale anche la pena di notare alcuni vincoli relativi alle risorse. Innanzitutto, Android supporta solo un elenco lineare di file all'interno delle cartelle predefinite in res. Ad esempio, non supporta le cartelle nidificate sotto la cartella di layout (o le altre cartelle sotto res).

In secondo luogo, ci sono alcune somiglianze tra la cartella delle risorse e la cartella raw sotto res. Entrambe le cartelle possono contenere file raw, ma i file all'interno di raw sono considerati risorse e i file all'interno delle risorse non lo sono.

Si noti che poiché i contenuti della cartella delle risorse non sono considerati risorse, è possibile inserire una gerarchia arbitraria di cartelle e file al suo interno.


La risposta migliore di @eski è buona, ma il codice non è elegante da usare, quindi ho scritto uno script groove in gradle per uso generale. È applicato a tutti i tipi di build e al gusto del prodotto e non solo può essere utilizzato per il layout, è anche possibile aggiungere una sottocartella per qualsiasi altro tipo di risorsa, ad esempio drawable. Ecco il codice (mettilo nel blocco android del file gradle a livello di progetto):

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

Come fare in pratica?

Ad esempio, desidero creare una sottocartella denominata activity per il layout , aggiungere una stringa con qualsiasi nome nella variabile resDirs come i layouts , quindi il file xml di layout deve essere inserito in res\layouts\activity\layout\xxx.xml .

Se voglio creare sottocartelle denominate selectors per drawable , aggiungi una stringa con qualsiasi nome nella variabile resDirs come drawables , quindi il file xml drawable dovrebbe essere messo in res\drawables\selectors\drawable\xxx.xml .

Il nome della cartella come layouts e drawables è definito nella variabile resDirs , può essere qualsiasi stringa. Tutte le sottocartelle create dall'utente come activity o selectors sono considerate uguali alla cartella res . Quindi, nella cartella dei selectors , dobbiamo creare anche una cartella drawable e mettere i file xml in una cartella drawable , dopo che gradle può riconoscere i file xml come disegnabili normalmente.


Non possibile, ma la cartella di layout è ordinata per nome. Quindi, antepongo i nomi dei file di layout con i nomi dei miei pacchetti. Ad esempio per i due pacchetti "acquisto" e "riproduzione":

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

Ora con Android Studio e Gradle, puoi avere più cartelle di risorse nel tuo progetto. Consentendo di organizzare non solo i file di layout ma qualsiasi tipo di risorse.

Non è esattamente una sottocartella, ma può separare parti della tua applicazione.

La configurazione è così:

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

Controlla la documentazione .


Penso che la soluzione più elegante a questo problema (dato che le sottocartelle non sono consentite) è di anteporre i nomi dei file al nome della cartella in cui l'avresti inserito. Ad esempio, se disponi di una serie di layout per un'attività, un frammento o solo una vista generale chiamata "luoghi", dovresti semplicemente aggiungerla a places_my_layout_name. Almeno questo risolve il problema di organizzarli in modo che siano più facili da trovare all'interno dell'IDE. Non è la soluzione più impressionante, ma è meglio di niente.


Puoi farlo con gradle. Ho realizzato un progetto dimostrativo che mostra come.

Il trucco consiste nell'utilizzare la capacità di Gradle di unire più cartelle di risorse e impostare la cartella res e le sottocartelle nidificate nel blocco sourceSets.

La stranezza è che non è possibile dichiarare una cartella di risorse contenitore prima di dichiarare le cartelle delle risorse figlio della cartella.

Di seguito è riportato il blocco sourceSets dal file build.gradle della demo. Si noti che le sottocartelle vengono dichiarate per prime.

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

Inoltre, il genitore diretto dei tuoi file di risorse reali (pngs, layout xml, ecc.) Deve comunque corrispondere alle specification .


Se utilizzi il metodo nella risposta approvata e desideri migliorarlo un po ', modifica l'impostazione gradle in questo modo:

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

Pertanto, se aggiungi altre cartelle e layout, non è necessario tornare qui e aggiungere un lungo elenco di cartelle di origine, quindi lasciare a gradle recuperare tutte le cartelle.


Sebbene tutte le proposte per più set di risorse possano funzionare, il problema è che la logica corrente per il plug-in Android Studio Gradle non aggiornerà i file di risorse dopo che sono stati modificati per set di risorse annidate. L'attuale implementazione tenta di controllare le directory delle risorse usando startsWith (), quindi una struttura di directory che è annidata (es. Src / main / res / layout / layouts e src / main / res / layout / layouts_category2) sceglierà src / main / res / layout / layout in modo coerente e mai effettivamente aggiornare le modifiche. Il risultato finale è che devi ricostruire / pulire il progetto ogni volta.

Ho inviato una patch su https://android-review.googlesource.com/#/c/157971/ per provare a risolvere il problema.


Uso il plug-in Raggruppamento file Android per Android Studio. In realtà non consente di creare sottocartelle, ma può VISUALIZZARE i file e le risorse poiché si trovano in cartelle diverse. E questo è esattamente quello che volevo.

Puoi installare il plug-in "Raggruppamento file Android" di

Finestre:

Android Studio -> File -> Impostazioni -> Plugin.

Mac:

Android Studio -> Scheda Android Studio (in alto a sinistra) -> Preferenze -> Plugin -> Installa il plugin JetBrains ..

Per Mac, sono riuscito a testarlo e non sono stato in grado di cercare il plug-in. Quindi ho scaricato il plug-in da here e ho usato l'opzione Install plugin from disk dall'impostazione precedente.


Volevo solo aggiungere la fantastica risposta di Eskis alle persone che hanno problemi. (Nota: questo funzionerà e apparirà come directory separate all'interno della vista 'progetto', non sfortunatamente nella vista 'android').

Testato con il seguente. BuildToolsVersion = 23.0.0 gradle 1.2.3 e 1.3.0

Questo è il modo in cui ho il mio per lavorare con un progetto già costruito.

  1. Copia tutti i file XML dalla tua directory di layout e inseriscili in una directory sul desktop o qualcosa per il backup.
  2. Elimina l'intera directory di layout (assicurati di aver eseguito il backup di tutto dal punto 1 !!!)
  3. Fare clic con il tasto destro del mouse sulla directory res e selezionare new> directory.
  4. Dai un nome a questa nuova directory "layout". (Questo può essere quello che vuoi, ma non sarà una directory 'frammento' o 'attività', che verrà dopo).
  5. Fare clic con il pulsante destro del mouse sulla nuova directory "layouts" e selezionare new> directory. (Questo sarà il nome del tipo di file XML che avrai in esso, ad esempio "frammenti" e "attività").
  6. Fai clic con il pulsante destro del mouse sulla directory 'frammento' o 'attività' (Nota: questo non deve essere 'frammento' o 'attività' è solo quello che sto usando come esempio) e selezionare di nuovo> directory ancora una volta e nominare questa directory "disposizione". (Nota: questo DEVE essere chiamato 'layout' !!! molto importante).
  7. Inserisci i file XML che desideri all'interno della nuova directory 'layout' dal backup eseguito sul desktop.
  8. Ripeti i passaggi 5 - 7 per tutte le directory personalizzate che desideri.
  9. Una volta completato, vai nel tuo file gradle.build dei moduli e crea una definizione sourceSets come questa ... (Assicurati che 'src / main / res / layouts' e 'src / main / res' siano sempre i due più in basso !! !! Come sto mostrando qui sotto).

    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. Profitto $$$$

Ma sul serio ... è così che ho potuto farlo funzionare. Fammi sapere se qualcuno ha qualche domanda ... Posso provare ad aiutare.

Le immagini valgono più delle parole.





android-layout