web-dev-qa-db-fra.com

Le dossier Android Layout peut-il contenir des sous-dossiers?

À l’heure actuelle, je stocke chaque fichier de présentation XML dans le dossier res/layout. Il est donc simple et pratique de gérer de petits projets. Toutefois, lorsqu’il s’agit de projets volumineux et lourds, une hiérarchie doit être créée. sous-dossiers nécessaires dans le dossier de présentation.

par exemple.

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

De la même manière, nous aimerions avoir des sous-dossiers pour la grande application. Y a-t-il moyen de le faire dans le projet Android?

Je suis en mesure de créer des sous-dossiers layout-personal et layout_address dans le dossier de présentation, mais lorsque vient le temps d'accéder au fichier de présentation XML à l'aide de R.layout ._______, il n'existe à ce moment-là aucune fenêtre contextuelle de présentation XML dans le dossier. m e n u.

513
Paresh Mayani

Vous POUVEZ faire cela avec Gradle. J'ai fait un projet de démonstration montrant comment.

L'astuce consiste à utiliser la capacité de gradle à fusionner plusieurs dossiers de ressources et à définir le dossier res ainsi que les sous-dossiers imbriqués dans le bloc sourceSets.

Le problème, c'est que vous ne pouvez pas déclarer un dossier de ressources de conteneur avant de déclarer les dossiers de ressources enfants de ce dossier.

Ci-dessous se trouve le bloc sourceSets du fichier build.gradle de la démo. Notez que les sous-dossiers sont déclarés en premier.

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

nested resources picture

De plus, le parent direct de vos fichiers de ressources actuels (pngs, mises en page xml, etc.) doit toujours correspondre à spécification .

454
eski

La réponse est non.

Je voudrais attirer votre attention sur ce livre Pro Android 2 qui dit:

Il convient également de noter quelques contraintes en matière de ressources. Tout d'abord, Android ne prend en charge qu'une liste linéaire de fichiers dans les dossiers prédéfinis sous res. Par exemple, il ne prend pas en charge les dossiers imbriqués sous le dossier de présentation (ou les autres dossiers sous res).

Deuxièmement, il existe des similitudes entre le dossier assets et le dossier raw sous res. Les deux dossiers peuvent contenir des fichiers bruts, mais les fichiers contenus dans les fichiers bruts sont considérés comme des ressources, contrairement aux fichiers des ressources.

Notez que, dans la mesure où le contenu du dossier actifs n'est pas considéré comme une ressource, vous pouvez placer une hiérarchie arbitraire de dossiers et fichiers dans il.

230
100rabh

Je voulais juste ajouter une réponse fantastique à eskis pour les personnes en difficulté. (Remarque: cela ne fonctionnera que et ressemblera à des répertoires distincts dans la vue "projet", pas à la vue "Android", malheureusement.)

Testé avec ce qui suit. BuildToolsVersion = 23.0.0 Gradle 1.2.3 & 1.3.0

C’est ainsi que j’ai eu le mien de travailler avec un projet déjà construit.

  1. Copiez tous les fichiers XML à partir de votre répertoire de mise en page et placez-les dans un répertoire du bureau ou dans un répertoire de sauvegarde.
  2. Supprimer tout le répertoire de mise en page (Assurez-vous de tout sauvegarder à partir de l'étape 1 !!!)
  3. Cliquez avec le bouton droit sur le répertoire res et sélectionnez new> directory.
  4. Nommez ce nouveau répertoire "layouts". (Cela peut être ce que vous voulez, mais ce ne sera pas un répertoire "fragment" ou "activité", cela viendra plus tard).
  5. Cliquez avec le bouton droit sur le nouveau répertoire "layouts" et sélectionnez new> directory. (Ce sera le nom du type de fichier XML que vous aurez, par exemple, "fragments" et "activités").
  6. Faites un clic droit sur le répertoire 'fragment' ou 'activités' (Remarque: cela ne doit pas nécessairement être 'fragment' ou 'activités', c'est exactement ce que j'utilise comme exemple) et sélectionnez à nouveau new> directory et nommez ce répertoire. "disposition". (Note: Ceci DOIT être nommé 'layout' !!! très important).
  7. Placez les fichiers XML de votre choix dans le nouveau répertoire "layout" à partir de la sauvegarde effectuée sur votre bureau.
  8. Répétez les étapes 5 à 7 pour autant de répertoires personnalisés que vous le souhaitez.
  9. Une fois que cela est terminé, allez dans le fichier de vos modules gradle.build et créez une définition sourceSets comme celle-ci ... (Assurez-vous que 'src/main/res/layouts' et 'src/main/res' sont toujours les deux derniers!! !! Comme je montre ci-dessous).

    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. Bénéfice $$$$

Mais sérieusement… c'est comme ça que je l'ai fait fonctionner. Faites-moi savoir si quelqu'un a des questions .. Je peux essayer de vous aider.

Les images valent plus que des mots.

Directory Structure

75
hitch.united

Impossible, mais le dossier de présentation est trié par nom. Donc, je préfixe les noms de fichier de mise en page avec mes noms de paquet. Par exemple. pour les deux forfaits "achat" et "jeu":

buying_bought_tracks.xml
buying_buy_tracks.xml
playing_edit_playlist.xml
playing_play_playlist.xml
playing_show_playlists.xml
52
delformo

J'utilise Android File Grouping plug-in pour Android Studio.Il ne vous permet pas vraiment de créer des sous-dossiers, mais il peut afficher vos fichiers et ressources car ils sont dans des dossiers différents . Et c'est exactement ce que je voulais.

Vous pouvez installer le plugin "Android File Grouping" en

Les fenêtres:

Android Studio -> Fichier -> Paramètres -> Plugins.

Mac:

Android Studio -> AndroidOnglet Studio (en haut à gauche) -> Préférences -> Plug-ins -> Installer le plug-in JetBrains ..

Pour Mac, j'ai pu le tester et je n'ai pas pu rechercher le plugin. J'ai donc téléchargé le plugin depuis ici et utilisé l'option Install plugin from disk du paramètre ci-dessus.

19
Sharpe

Maintenant, avec Android Studio et Gradle, vous pouvez avoir plusieurs dossiers de ressources dans votre projet. Permettant d'organiser non seulement vos fichiers de mise en page, mais tout type de ressources.

Ce n'est pas exactement un sous-dossier, mais peut séparer des parties de votre application.

La configuration est la suivante:

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

Vérifiez le documentation .

18
Androiderson

Je pense que la solution la plus élégante à ce problème (étant donné que les sous-dossiers ne sont pas autorisés) est de faire précéder les noms de fichiers du nom du dossier dans lequel vous l'auriez placé. Par exemple, si vous avez plusieurs mises en page pour une activité, un fragment ou simplement une vue générale appelée "lieux", vous devez simplement l'ajouter à la fin avec places_my_layout_name. Au moins, cela résout le problème de leur organisation de manière à ce qu’ils soient plus faciles à trouver dans l’EDI. Ce n'est pas la solution la plus géniale, mais c'est mieux que rien.

16
botbot

Petit problème

Je peux obtenir des sous-dossiers en suivant le réponse du haut à cette question.

Cependant, au fur et à mesure que le projet grossit, vous aurez plusieurs sous-dossiers:

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

Pas un gros problème, mais:

  • ce n'est pas joli car la liste devient très longue.
  • vous devez changer votre app/build.gradle chaque fois que vous ajoutez un nouveau dossier.

Amélioration

J'ai donc écrit une méthode Groovy simple pour récupérer tous les dossiers imbriqués:

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
}

Collez cette méthode en dehors du bloc Android {...} dans votre app/build.gradle.


Comment utiliser

Pour une structure comme celle-ci:

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

Utilisez-le comme ceci:

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

Si vous avez une structure comme celle-ci:

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

Vous allez l'utiliser comme ça:

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

Explication

getLayoutList() prend a relative path comme argument. Le relative path est relatif à la racine du projet. Ainsi, lorsque nous saisirons "app/src/main/res/layouts/", il renverra le nom de tous les sous-dossiers sous la forme d'un tableau, qui sera exactement le même que:

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

Voici le script avec des commentaires pour la compréhension:

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
}

J'espère que ça aide!

15
I'm a frog dragon

Maintenant, nous pouvons facilement faire avec le plugin JetBrains appelé " Android File Grouping "

consultez ce lien

Regroupement de fichiers Android

enter image description here

11

Une façon dont je l'ai fait était de créer un dossier de res séparé au même niveau que le dossier de res réel dans votre projet, vous pouvez ensuite l'utiliser dans votre application build.gradle

Android {
    //other stuff

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

example folder structure

alors chaque sous-dossier de votre nouveau dossier res peut être quelque chose concernant chaque écran particulier ou quelque chose dans votre application, et chaque dossier aura son propre layout/drawable/values etc gardant les choses organisées et vous n'avez pas besoin de mettre à jour le fichier gradle manuellement, comme le demandent certaines de ces autres réponses (il suffit de synchroniser votre diplôme chaque fois que vous ajoutez un nouveau dossier de ressources pour qu'il le sache, et assurez-vous d'ajouter les sous-dossiers appropriés avant d'ajouter vos fichiers xml) .

5
Fonix

Vérifiez script Bash Flatten Folder qui convertit la hiérarchie des dossiers en un seul dossier

4
Sneg

Si vous développez sur un Linux ou un Mac, une solution de contournement consisterait à créer des sous-dossiers contenant des liens symboliques vers vos fichiers de mise en page. Utilisez simplement la commande ln avec -s

ln -s PATH_TO_YOUR_FILE

Le problème avec ceci est que votre dossier Layout contient toujours tous les fichiers .xml. Mais vous pouvez bien sûr les sélectionner en utilisant les sous-dossiers. C'est la chose la plus proche de ce que vous voudriez avoir.

Je viens de lire que cela pourrait fonctionner avec Windows également si vous utilisez Vista ou une version ultérieure. Il y a cette commande mklink. Il suffit de google, je ne l'ai jamais utilisé moi-même.

Un autre problème est que, si le fichier est ouvert et que vous essayez de le rouvrir, le plug-in génère une exception de pointeur NULL. Mais ça ne raccroche pas.

3
Darokthar

La meilleure réponse de @ eski est bonne, mais le code n’est pas élégant à utiliser; j’ai donc écrit un script groovy en dégradé pour un usage général. Il s'applique à tous les types de construction et toutes les variantes de produit. En plus de pouvoir être utilisé pour la présentation, vous pouvez également ajouter un sous-dossier pour tout autre type de ressource tel que drawable. Voici le code (mettez-le dans le bloc Android du fichier de niveaux au niveau du projet):

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

Comment faire en pratique?

Par exemple, je veux créer un sous-dossier nommé activity pour layout, ajouter une chaîne portant un nom quelconque dans la variable resDirs telle que layouts, puis le fichier de présentation XML doit être placé dans res\layouts\activity\layout\xxx.xml.

Si je veux créer un sous-dossier nommé selectors pour drawable, ajoutez une chaîne portant un nom quelconque dans la variable resDirs telle que drawables, le fichier xml dessinable doit être placé dans res\drawables\selectors\drawable\xxx.xml.

Le nom du dossier tel que layouts et drawables est défini dans la variable resDirs, il peut s'agir de n'importe quelle chaîne. Tous les sous-dossiers créés par vous, tels que activity ou selectors, sont considérés comme identiques au dossier res. Donc, dans le dossier selectors, nous devons créer le dossier drawable en plus et placer les fichiers xml dans le dossier drawable, après quoi le gradé pourra reconnaître les fichiers xml comme pouvant être dessinés normalement.

3
AvatarQing

Bien que toutes les propositions pour plusieurs ensembles de ressources puissent fonctionner, le problème est que la logique actuelle du plug-in Android Studio Gradle ne mettra pas à jour les fichiers de ressources après leur modification pour les ensembles de ressources imbriqués. L'implémentation actuelle tente de vérifier les répertoires de ressources à l'aide de startsWith (). Par conséquent, une structure de répertoires imbriquée (par exemple, src/main/res/layout/layouts et src/main/res/layout/layouts_category2) choisira src/main/res./layout/layouts de manière cohérente et ne met jamais à jour les modifications. Le résultat final est que vous devez reconstruire/nettoyer le projet à chaque fois.

J'ai soumis un correctif à l'adresse https://Android-review.googlesource.com/#/c/157971/ pour essayer de résoudre le problème.

3
rogerhu

Si vous utilisez la méthode dans la réponse approuvée et que vous souhaitez l’améliorer un peu, modifiez le paramètre de dégradé comme suit:

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

Donc, si vous ajoutez plus de dossiers et de dispositions, vous n'avez pas besoin de revenir ici et d'ajouter une longue liste de dossiers sources, laissez gradle obtenir tous les dossiers pour vous.

2
Drusantia
  • Étape 1: Faites un clic droit sur la mise en page - afficher dans l'explorateur
  • Étape 2: Ouvrez le dossier de présentation et créez les sous-dossiers directement: layout_1, layout_2 ...
  • Étape 3: ouvrez le layout layout_1 create folder (remarque: le nom obligatoire est layout), ouvrez le dossier layout_2, créez le sous-répertoire create layout (remarque: le nom obligatoire est le layout) ...
  • Étape 4: Copiez les fichiers XML dans les sous-répertoires de présentation de layout_1 et de layout_2.
  • Étape 5: Exécutez le code dans buid.grade (application du module) et appuyez sur Sync maintenant:

sourceSets {
    main {
        res.srcDirs =
            [
                'src / main / res / layout / layout_1'
                'src / main / res / layout / layout_2',
                'src / main / res'
            ]
    }
}
  • Étape 6: Résumé: Toutes les étapes ci-dessus aideront uniquement à regrouper les dossiers et à les afficher en mode "projet", tandis que le mode "Android" s'affichera normalement.
  • Je tire donc que nommer les préfixes est aussi efficace que la mise en cluster de dossiers.
1
O Thạnh Ldt

Les principales réponses ont plusieurs inconvénients: vous devez ajouter de nouveaux chemins de présentation, AS place de nouvelles ressources dans le dossier res\layouts au lieu de res\values.

En combinant plusieurs réponses, j'ai écrit de manière similaire:

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

J'ai créé des dossiers avec cet article: http://alexzh.com/tutorials/how-to-store-layouts-in-different-folders-in-Android-project/ . Pour créer des sous-dossiers, vous devez utiliser ce menu: Nouveau> Dossier> Dossier Res.

UPDATE

Après quelques semaines, j’ai constaté que les changements de ressources ne sont pas remarqués par Android Studio . Donc, des bugs étranges apparaissent. Par exemple, les mises en page continuent d'afficher les anciennes tailles et marges. Parfois, AS ne trouve pas de nouveaux fichiers XML (en particulier lors de l'exécution). Parfois, il mélange view ids (références à un autre fichier XML). Il est souvent nécessaire d'appuyer sur Build > Clean Project ou Build > Rebuild Project. Lire Reconstruction requise après la modification des fichiers de présentation XML dans Android Studio .

0
CoolMind

Eh bien, la réponse courte est non. Mais vous pouvez certainement avoir plusieurs dossiers res. Je pense que cela est aussi proche que possible des sous-dossiers du dossier layout. Voici comment vous le faites.

0
sravan953