Le dossier de disposition Android peut-il contenir des sous-dossiers?

En ce moment, je stocke chaque fichier de mise en page xml dans le dossier res/layout , il est donc possible et simple de gérer de petits projets, mais quand il y a des projets volumineux et lourds, il devrait y avoir une hiérarchie et des sous-projets. dossiers requirejs dans le dossier de mise en page.

par exemple

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

De la même façon, nous aimerions avoir des sous-dossiers pour les applications volumineuses. Y at-il un 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 layout, mais lorsque vient le temps d’accéder au fichier de présentation xml à l’aide de R.layout ._______, il n’ya à ce moment aucune menu.

Vous POUVEZ le faire 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 nesteds dans le bloc sourceSets.

La particularité 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.

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

image de ressources imbriquées

De plus, le parent direct de vos fichiers de ressources réels (pngs, dispositions XML, etc.) doit toujours correspondre à la spécification .

La réponse est non.

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

Il convient également de noter quelques contraintes concernant les 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 nesteds sous le dossier de présentation (ou les autres dossiers sous res).

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

Notez que le contenu du dossier des ressources n’est pas considéré comme une ressource, vous pouvez y placer une hiérarchie arbitraire de dossiers et de fichiers .

Je voulais juste append à la réponse fantastique de eskis pour les personnes ayant des problèmes. (Remarque: Cela ne fonctionnera que comme des répertoires séparés dans la vue «projet», et non la vue «Android» malheureusement.)

Testé avec le suivant BuildToolsVersion = 23.0.0 Gradle 1.2.3 & 1.3.0

C’est comme ça que j’ai fait travailler les miennes avec un projet déjà construit.

  1. Copiez tous les fichiers XML de votre répertoire de mise en page et placez-les dans un répertoire sur le bureau ou quelque chose pour la sauvegarde.
  2. Supprimer tout le répertoire de mise en page (Assurez-vous d’avoir tout sauvegardé à 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 un répertoire ‘activity’, 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 dans ce fichier, par exemple, “fragments” et “activités”).
  6. Cliquez avec le bouton droit de la souris sur le répertoire ‘fragment’ ou ‘activities’ (Remarque: il ne doit pas nécessairement s’agir de ‘fragment’ ou ‘activités’) et sélectionnez new> directory pour nommer ce répertoire. “disposition”. (Remarque: Ceci DOIT être nommé “layout” !!! très important).
  7. Placez les fichiers XML de votre choix dans le nouveau répertoire “layout” de la sauvegarde que vous avez 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 cette opération terminée, accédez au fichier gradle.build de vos modules et créez une définition sourceSets comme celle-ci … (Assurez-vous que “src / main / res / layouts” & “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. Profit $$$$

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 d’aider.

Les images valent plus que les mots.

Structure du répertoire

Pas possible, mais le dossier de disposition est sortingé par nom. Donc, je ajoute les noms des fichiers de mise en page à mes noms de paquet. Par exemple pour les deux paquets “acheter” et “jouer”:

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

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 comme ceci:

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

Vérifiez la documentation .

J’utilise le plugin Android File Grouping pour Android Studio.Il ne vous permet pas vraiment de créer des sous-dossiers, mais il peut AFFICHER vos fichiers et ressources AS dans différents dossiers. Et c’est exactement ce que je voulais.

Vous pouvez installer le plug-in “Android File Grouping” par

Les fenêtres:

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

Mac:

Android Studio -> Onglet Android Studio (en haut à gauche) -> Préférences -> Plugins -> 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 à partir d’ ici et utilisé l’option Install plugin from disk dans le paramètre ci-dessus.

Je pense que la solution la plus élégante à ce problème (étant donné que les sous-dossiers ne sont pas autorisés) consiste à append les noms de fichiers au nom du dossier dans lequel vous les avez placés. Par exemple, si vous avez un ensemble de dispositions pour une activité, un fragment ou simplement une vue générale appelée “places”, vous devez simplement la placer 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.

Petit problème

Je suis capable de réaliser des sous-dossiers en suivant la première réponse à cette question.

Cependant, à 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 saisir tous les dossiers nesteds:

 def getLayoutList(path) { File file = new File(path) def throwAway = file.path.split("/")[0] def newPath = file.path.subssortingng(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:

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

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

Vous allez l'utiliser comme ceci:

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

Explication

getLayoutList() prend a relative path en tant qu'argument. Le relative path est relatif à la racine du projet. Ainsi, lorsque nous entrerons "app/src/main/res/layouts/" , le nom de tous les sous-dossiers sera affiché sous forme de tableau, ce qui sera exactement le même:

  [ '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 comprendre:

 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.subssortingng(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 cela aide!

Maintenant, nous pouvons facilement faire avec le plug-in JetBrains appelé ” Android File Grouping

consultez ce lien

Groupement de fichiers Android

entrer la description de l'image ici

Vérifier le script Bash Flatten Folder qui convertit la hiérarchie de dossiers en un seul dossier

Une façon dont je l’ai fait était de créer un dossier res distinct au même niveau que le dossier res réel de votre projet, vous pouvez alors l’utiliser dans vos apps build.gradle

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

exemple de structure de dossier

alors chaque sous-dossier de votre nouveau dossier res peut être quelque chose lié à chaque écran particulier ou quelque chose dans votre application, et chaque dossier aura sa propre layout / drawable / values etc. Parmi ces autres réponses, il vous suffit de synchroniser votre gradule chaque fois que vous ajoutez un nouveau dossier de ressources pour qu’il en soit informé, et assurez-vous d’append les sous-dossiers appropriés avant d’append vos fichiers XML.

Si vous développez sur une boîte Linux ou Mac, une solution consiste à 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 est que votre dossier de mise en page contient toujours tous les fichiers .xml. Mais vous pouvez les sélectionner en utilisant les sous-dossiers. C’est la chose la plus proche de ce que vous aimeriez avoir.

Je viens de lire, que cela pourrait fonctionner avec Windows également si vous utilisez Vista ou plus tard. Il y a cette commande mklink . Il suffit de le 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 l’ouvrir à nouveau, le plug-in génère une exception de pointeur NULL. Mais il ne raccroche pas.

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 met pas à jour les fichiers de ressources après leur modification pour les jeux de ressources nesteds. L’implémentation actuelle tente de vérifier les répertoires de ressources à l’aide de startsWith (), ainsi une structure de répertoire nestede (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 jamais mettre à jour les modifications. Le résultat final est que vous devez reconstruire / nettoyer le projet à chaque fois.

J’ai envoyé un correctif sur https://android-review.googlesource.com/#/c/157971/ pour essayer de résoudre les problèmes.

La meilleure réponse de @eski est bonne, mais le code n’est pas élégant à utiliser, alors j’ai écrit un script groovy en graduel pour un usage général. Il est appliqué à tous les types de construction et à toutes les variantes de produit. Vous pouvez non seulement l’utiliser pour la mise en page, mais vous pouvez également append un sous-dossier pour tout autre type de ressource, tel que le dessin. Voici le code (placez-le dans le bloc android du fichier de gradation 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 une activity nommée de sous-dossier pour la layout , append une chaîne par n’importe quel nom dans la variable resDirs telle que les layouts , puis le fichier XML de présentation doit être placé dans res\layouts\activity\layout\xxx.xml .

Si je veux créer des selectors nommés sous-dossier pour drawable , append une chaîne par n’importe quel nom dans la variable resDirs telle que drawables , puis le fichier xml pouvant être dessiné doit être placé dans res\drawables\selectors\drawable\xxx.xml .

Le nom du dossier, comme les layouts en layouts et les 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 l’ activity ou les selectors sont considérés comme identiques au dossier res . Donc, dans le dossier selectors , nous devons également créer drawable dossier drawable et placer les fichiers xml dans drawable dossier drawable , après quoi ce fichier peut reconnaître les fichiers XML comme pouvant être dessinés normalement.

  • Étape 1: Cliquez avec le bouton droit sur la mise en page – affichez-la dans l’explorateur
  • Étape 2: Ouvrez le dossier de disposition et créez directement les sous-dossiers: layout_1, layout_2 …
  • Étape 3: ouvrir layout_1 créer la mise en page du dossier (note: le nom obligatoire est la mise en page), ouvrir le dossier layout_2 create subdirectory (note: le nom obligatoire est la mise en page) …
  • Étape 4: Copiez les fichiers xml dans les sous-répertoires de présentation dans layout_1 et 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» sera affiché normalement.
  • Donc, je dessine que peut-être les préfixes de nommage sont aussi efficaces que les dossiers de clustering.

Si vous utilisez la méthode dans la réponse approuvée et que vous souhaitez l’améliorer, modifiez le paramètre de graduation 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 mises en page, vous n’avez pas besoin de revenir ici et d’append une longue liste de dossiers sources, laissez graduer tous les dossiers pour vous.

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

Les réponses supérieures ont plusieurs inconvénients: vous devez append de nouveaux chemins de disposition, AS place de nouvelles ressources dans le dossier res\layouts au lieu de res\values .

En combinant plusieurs réponses, j’ai écrit la même chose:

 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 de résolution.

METTRE À JOUR

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 à 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 les view id (références à un autre fichier XML). Il est souvent nécessaire d’appuyer sur Build > Clean Project ou Build > Rebuild Project . Lire la reconstruction requirejse après la modification des fichiers de disposition xml dans Android Studio .