Android布局文件夹是否可以包含子文件夹?

现在,我将每个xml布局文件存储在布局文件夹中,所以pipe理小型项目是可行和简单的,但是当存在大型和繁重项目的情况时,应该有一个层次结构和子文件夹布局文件夹。

例如

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

就像同样的方式,我们希望有大型应用程序的子文件夹,所以有没有办法在android项目中这样做?

我能够在layout文件夹内创buildlayout-personal和layout_address子文件夹,但是当使用R.layout访问xml布局文件的时候。 _ ,那时菜单里面没有任何xml布局popup。

你可以用gradle来做到这一点。 我做了一个演示项目,展示了如何。

诀窍是使用gradle的能力来合并多个资源文件夹 ,并设置res文件夹以及sourceSets块中的嵌套子文件夹。

奇怪的是,在声明该文件夹的子资源文件夹之前,您无法声明容器资源文件夹。

以下是演示中的build.gradle文件的sourceSets块。 请注意,子文件夹是首先声明的。

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

嵌套的资源图片

此外,您的实际资源文件(PNG,XML布局等)的直接父母仍然需要符合规范 。

答案是不。

我想提请你注意这本书的专业Android 2 ,指出:

同样值得注意的是对资源的一些限制。 首先,Android仅支持res下的预定义文件夹中的线性列表文件。 例如,它不支持布局文件夹下的嵌套文件夹 (或res下的其他文件夹)。

其次,资源文件夹和res下的原始文件夹之间有一些相似之处。 这两个文件夹都可以包含原始文件,但原始文件中的文件被认为是资源,而资产中的文件则不是。

请注意,由于资产文件夹的内容不被视为资源,因此您可以在其中放置任意层级的文件夹和文件

我只是想为有困难的人添加eskis'梦幻般的答案。 (注意:这只会在'项目'视图内看起来像单独的目录,不幸的是'android'视图。

testing以下。 BuildToolsVersion = 23.0.0 gradle 1.2.3&1.3.0

这就是我如何与已经build成的项目合作。

  1. 将所有的XML文件从你的布局目录中拷贝出来,放到桌面上的某个目录或备份。
  2. 删除整个布局目录(确保你从第一步起备份了所有东西!!!)
  3. 右键单击res目录并select新build>目录。
  4. 命名这个新的目录“布局”。 (这可以是任何你想要的,但它不会是一个'片段'目录或'活动'目录,后来)。
  5. 右键单击新的“布局”目录并select新build>目录。 (这将是您将在其中包含的XML文件types的名称,例如“fragments”和“activities”)。
  6. 右键单击“片段”或“活动”目录(注意:这不一定是'片段'或'活动',这正是我用作例子),并再次select新>目录,并命名此目录“布局”。 (注:这必须命名为“布局”!!!非常重要)。
  7. 把你想要的XML文件放在你的桌面上的备份里面。
  8. 重复步骤5 – 7为您想要的自定义目录。
  9. 一旦完成,进入你的模块gradle.build文件,创build一个像这样的sourceSets定义…(确保'src / main / res / layouts'&'src / main / res'总是最下面的两个! !!就像我在下面显示)。

     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. 利润$$$$

但严重的是,这是我得到它的工作。 让我知道如果有人有任何问题..我可以尝试帮助。

图片比文字更有价值。

目录结构

不可能,但布局文件夹按名称sorting。 所以,我用我的包名称预先布局文件名称。 例如,对于“购买”和“玩”两个包:

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

现在使用Android Studio和Gradle,您的项目中可以有多个资源文件夹。 不仅可以组织您的布局文件,而且可以组织任何types的资源。

这不完全是一个子文件夹,但可能会分开你的应用程序的一部分。

configuration是这样的:

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

检查文档 。

我使用Android Studio的Android文件分组插件。它并不真的允许您创build子文件夹,但它可以显示您的文件和资源,因为它们在不同的文件夹中。 而这正是我想要的。

你可以通过安装“Android File Grouping”插件

视窗:

Android Studio – >文件 – >设置 – >插件。

苹果电脑:

Android Studio – > Android Studio Tab(左上angular) – >首选项 – >插件 – >安装JetBrains插件

对于Mac,我能够testing它,无法search插件。 所以我从这里下载了这个插件,并使用上面设置中的Install plugin from disk选项。

我认为这个问题的最优雅的解决scheme(考虑到子文件夹是不允许的)是用文件夹的名称预先放置文件名。 例如,如果您有一堆活动,片段或称为“场所”的普通视图,那么您应该在场景的前面添加places_my_layout_name。 至less可以解决在IDE中更容易查找的问题。 这不是最棒的解决scheme,但总比没有好。

小问题

通过回答这个问题的最佳答案 ,我能够实现子文件夹。

但是,随着项目越来越大,您将拥有许多子文件夹:

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

不是一个大问题,但是:

  • 因为名单变得很长,所以不太好。
  • 每次添加新文件夹时都必须更改app/build.gradle

起色

所以我写了一个简单的Groovy方法来抓取所有嵌套的文件夹:

 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 } 

将此方法粘贴到您的app/build.gradle中的android {...}app/build.gradle


如何使用

对于这样的结构:

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

像这样使用它:

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

如果你有这样的结构:

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

你会像这样使用它:

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

说明

getLayoutList()a relative path作为参数。 relative path是相对于项目的根。 所以当我们input"app/src/main/res/layouts/" ,它会把所有子文件夹的名字作为一个数组返回,

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

以下是有关理解评论的脚本:

 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 } 

希望它有帮助!

检查Bash Flatten文件夹脚本 ,将文件夹层次结构转换为单个文件夹

如果您正在开发一个Linux或Mac机箱,解决方法是创build子文件夹,其中包括到您的布局文件的符号链接。 只需使用-n命令即可

ln -s PATH_TO_YOUR_FILE

与此问题是,您的布局文件夹仍包含所有的.xml文件。 但是你可以通过使用子文件夹来select它们。 这是最接近你想要的东西。

我刚刚阅读,如果您使用Vista或更高版本,这也可以用于Windows。 有这个mklink命令。 只是谷歌它,从来没有用过它自己。

另一个问题是,如果你打开文件并尝试再次打开它,插件会抛出一个NULL指针exception。 但它不挂断。

尽pipe所有关于多个资源集的build议都可能工作,但问题是Android Studio Gradle插件的当前逻辑在嵌套资源集发生更改后不会更新资源文件。 当前的实现尝试使用startsWith()检查资源目录,因此嵌套的目录结构(即src / main / res / layout / layouts和src / main / res / layout / layouts_category2)将selectsrc / main / res /布局/布局一致,永远不会实际更新更改。 最终的结果是你必须每次重build/清理项目。

我在https://android-review.googlesource.com/#/c/157971/上提供了一个补丁来尝试帮助解决问题。;

@eski最好的答案是好的,但是代码不够高雅,所以我写了一个Groovy脚本来用于一般用途。 它适用于所有构buildtypes和产品风格,不仅可以用于布局,还可以为任何其他资源types(如drawable)添加子文件夹。 这里是代码(把它放在项目级的gradle文件的android块中):

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

如何在实践中?

例如,我想为layout创build一个名为activity子文件夹,在resDirsvariables(比如layout )中添加一个任意名字的string,然后将布局xml文件放在res\layouts\activity\layout\xxx.xml

如果我想创build一个名为selectors子文件夹来drawable ,可以在resDirsvariables中添加任何名字的string,例如drawables ,那么可绘制的xml文件应该放在res\drawables\selectors\drawable\xxx.xml

resDirsvariables中定义了文件夹名称,如layoutsdrawables ,它可以是任何string。 您创build的所有子文件夹(如activityselectors都被视为与res文件夹相同。 因此,在selectors文件夹中,我们必须另外创builddrawable文件夹,并将xml文件放在drawable文件夹中,之后gradle才能将xml文件正常识别为drawable。

我做的一个方法是创build一个单独的res文件夹在同一级别作为您的项目中的实际res文件夹,然后你可以在你的应用程序build.gradle

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

示例文件夹结构

那么你的新res文件夹中的每个子文件夹可以是与你的应用程序中的每个特定的屏幕或东西有关的东西,每个文件夹将有他们自己的layout / drawable / values等等保持组织和你不必手动更新gradle文件这些其他答案的要求。

现在我们可以轻松地使用名为“ Android文件分组 ”的JetBrains插件

看看这个链接

Android文件分组

在这里输入图像描述

那么简单的答案是否定的。 但你绝对可以有多个res文件夹。 我认为,这是尽可能接近layout文件夹的子文件夹。 这是你如何做到的。