现在,我将每个xml布局文件存储在res/layout
文件夹中,因此管理小项目是可行且简单的,但是当存在大型和重型项目的情况时,那么应该是布局文件夹中所需的层次结构和子文件夹。
例如
layout
-- layout_personal
-- personal_detail.xml
-- personal_other.xml
--layout_address
-- address1.xml
-- address2.xml
以同样的方式,我们希望为大型应用程序提供子文件夹,那么有没有办法在android项目中这样做?
我可以在布局文件夹中创建layout-personal和layout_address子文件夹,但是当使用R.layout ._______访问xml布局文件的时候,那时没有任何xml布局弹出 - 在菜单里面。
答案 0 :(得分:449)
你可以用gradle做到这一点。我已经制作了demo project来展示如何。
诀窍是使用gradle的merge multiple resource folders能力,并设置res文件夹以及sourceSets块中的嵌套子文件夹。
怪癖是,在声明该文件夹的子资源文件夹之前,您无法声明容器资源文件夹。
以下是demo中build.gradle文件中的sourceSets块。请注意,子文件夹首先被声明。
sourceSets {
main {
res.srcDirs =
[
'src/main/res/layouts/layouts_category2',
'src/main/res/layouts',
'src/main/res'
]
}
}
此外,实际资源文件的直接父级(png,xml布局等)仍然需要与specification对应。
答案 1 :(得分:231)
答案是否定的。
我想提请你注意这本书Pro Android 2:
值得注意的还有一些 关于资源的限制。 首先,Android仅支持线性 预定义内的文件列表 res下的文件夹。例如,它 不支持嵌套文件夹 布局文件夹(或其他 res下的文件夹。
其次,有一些相似之处 资产文件夹和原始文件夹之间 res下的文件夹。这两个文件夹都可 包含原始文件,但包含文件 原始内部被视为资源 并且资产中的文件不是。
注意因为内容了 资产文件夹不予考虑 资源,你可以把任意 中的文件夹和文件的层次结构 它
答案 2 :(得分:75)
我只是想为有困难的人添加eskis的精彩答案。 (注意:这只会起作用,看起来像'项目'视图中的单独目录,不幸的是不是'android'视图。)
使用以下测试。 BuildToolsVersion = 23.0.0 gradle 1.2.3& 1.3.0
这就是我使用已经建成的项目的方法。
完成后,进入你的模块gradle.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'
]
}
}
Profit $$$$
但是说真的......这就是我开始工作的方式。如果有人有任何问题,请告诉我。我可以尝试提供帮助。
图片不仅仅是文字。
答案 3 :(得分:52)
不可能,但布局文件夹按名称排序。所以,我在布局文件名前加上我的包名。例如。两个包“购买”和“玩”:
buying_bought_tracks.xml
buying_buy_tracks.xml
playing_edit_playlist.xml
playing_play_playlist.xml
playing_show_playlists.xml
答案 4 :(得分:19)
我为Android Studio使用Android File Grouping插件。它实际上不允许您创建子文件夹,但它可以显示您的文件和资源,因为它们位于不同的文件夹中。这正是我想要的。
您可以通过
安装“Android文件分组”插件Windows:
Android Studio - >档案 - >设置 - >插件。
的Mac:
Android Studio - > Android Studio标签(左上角) - >偏好 - >插件 - >安装JetBrains插件..
对于Mac,我能够测试它并且无法搜索插件。所以我从here下载了该插件,并使用了上述设置中的Install plugin from disk
选项。
答案 5 :(得分:18)
现在使用Android Studio和Gradle,您可以在项目中拥有多个资源文件夹。允许不仅组织您的布局文件,还组织任何类型的资源。
它不完全是一个子文件夹,但可以部分应用程序。
配置如下:
sourceSets {
main {
res.srcDirs = ['src/main/res', 'src/main/res2']
}
}
答案 6 :(得分:16)
我认为这个问题最优雅的解决方案(假设不允许使用子文件夹)是在文件名前加上你将它放在里面的文件夹的名称。例如,如果您有一堆Activity,Fragment或只是名为“places”的一般视图的布局,那么您应该只使用places_my_layout_name作为前缀。至少这解决了以在IDE中更容易找到的方式组织它们的问题。这不是最棒的解决方案,但它总比没有好。
答案 7 :(得分:15)
我可以按照top answer这个问题来实现子文件夹。
但是,随着项目变大,您将拥有许多子文件夹:
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
}
将此方法粘贴到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
相对于项目的根目录。因此,当我们输入"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
}
希望它有所帮助!
答案 8 :(得分:10)
答案 9 :(得分:5)
我这样做的方法是在与项目中的实际res文件夹相同的级别创建一个单独的res文件夹,然后你可以在你的应用程序build.gradle中使用它。
android {
//other stuff
sourceSets {
main.res.srcDirs = ['src/main/res', file('src/main/layouts').listFiles()]
}
}
然后,新res文件夹的每个子文件夹都可以与您的应用中的每个特定屏幕相关联,并且每个文件夹都有自己的layout
/ drawable
/ values
等保持井井有条,你不必像其他一些答案那样手动更新gradle文件(每次添加新的资源文件夹时都要同步你的gradle,以便它知道它,并确保在添加你之前添加相关的子文件夹xml文件)。
答案 10 :(得分:4)
检查将文件夹层次结构转换为单个文件夹的Bash Flatten Folder script
答案 11 :(得分:3)
如果您正在开发Linux或Mac机箱,那么解决方法就是创建包含指向布局文件的符号链接的子文件夹。只需将ln命令与-s
一起使用即可ln -s PATH_TO_YOUR_FILE
问题是,您的Layout文件夹仍包含所有.xml文件。但您可以使用子文件夹选择它们。这是你最想要的东西。
我刚读过,如果您使用的是Vista或更高版本,这也适用于Windows。有mklink
命令。只是google它,从来没有用过它。
另一个问题是,如果您打开了文件并尝试再次打开它,则插件会抛出NULL指针异常。但它并没有挂断。
答案 12 :(得分:3)
@eski的最佳答案是好的,但代码使用起来并不优雅,所以我在gradle中编写了一个groovy脚本供一般使用。它适用于所有构建类型和产品风格,不仅可用于布局,还可以为任何其他资源类型(如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]
}
如何在实践中做到?
例如,我想为activity
创建名为layout
的子文件夹,在resDirs
变量中添加任意名称的字符串,例如layouts
,然后添加布局xml文件应该放在res\layouts\activity\layout\xxx.xml
。
如果我想为selectors
创建名为drawable
的子文件夹,请在resDirs
变量中添加任意名称的字符串,例如drawables
,那么可绘制的xml文件应为放入res\drawables\selectors\drawable\xxx.xml
。
layouts
和drawables
等文件夹名称在resDirs
变量中定义,可以是任何字符串。
您创建的所有子文件夹(例如activity
或selectors
)都被视为与res
文件夹相同。因此,在selectors
文件夹中,我们必须另外创建drawable
文件夹并将xml文件放在drawable
文件夹中,之后该gradle可以将xml文件正常识别为可绘制文件。
答案 13 :(得分:3)
虽然可以使用多个资源集的所有提议,但问题是Android Studio Gradle插件的当前逻辑在更改嵌套资源集后不会更新资源文件。当前实现尝试使用startsWith()检查资源目录,因此嵌套的目录结构(即src / main / res / layout / layouts和src / main / res / layout / layouts_category2)将选择src / main / res / layout / layouts一致,永远不会实际更新更改。最终结果是每次都必须重建/清理项目。
我在https://android-review.googlesource.com/#/c/157971/提交了一个补丁,试图帮助解决问题。
答案 14 :(得分:2)
如果您在批准的答案中使用该方法,并且想对它进行一点改进,则可以像下面这样更改gradle设置:
sourceSets {
main {
res.srcDirs = [
file("src/main/res/layouts/").listFiles(),
"src/main/res/layouts",
"src/main/res"
]
}
}
因此,如果您添加更多文件夹和布局,则无需返回此处并添加一长串源文件夹,让gradle为您获取所有文件夹。
答案 15 :(得分:1)
sourceSets {
main {
res.srcDirs =
[
'src / main / res / layout / layout_1'
'src / main / res / layout / layout_2',
'src / main / res'
]
}
}
答案 16 :(得分:0)
嗯,简短的回答是否定的。但你绝对可以拥有多个res
个文件夹。我认为,这与layout
文件夹的子文件夹一样接近。 Here's你是怎么做到的。
答案 17 :(得分:0)
最常见的答案有几个缺点:您必须添加新的布局路径,AS会将新资源放置到res\layouts
文件夹中,而不是res\values
上。
结合几个我写的类似答案:
sourceSets {
main {
res.srcDirs =
[
'src/main/res',
file("src/main/res/layouts/").listFiles(),
'src/main/res/layouts'
]
}
}
我在本文中制作了文件夹:http://alexzh.com/tutorials/how-to-store-layouts-in-different-folders-in-android-project/。为了创建子文件夹,您应该使用以下菜单:New> Folder> Res Folder。
更新
几周后,我发现Android Studio没有注意到资源变化。因此,出现了一些奇怪的错误。例如,布局继续显示旧尺寸,边距。有时,AS找不到新的XML文件(尤其是在运行时)。有时,它会混合view id
(对另一个XML文件的引用)。通常需要按Build > Clean Project
或Build > Rebuild Project
。阅读Rebuild required after changing xml layout files in Android Studio。
答案 18 :(得分:0)
不能轻松拥有子目录,但是可以拥有其他个资源文件夹。没有人惊讶,没有提到它,而是保留默认资源文件夹,并添加更多内容:
sourceSets {
main.res.srcDirs += ['src/main/java/XYZ/ABC']
}
答案 19 :(得分:0)
在一个模块中,要具有风味,风味资源(布局,值)和风味资源资源的组合,需要牢记的两件事是:
在res.srcDirs
中添加资源目录以获取风味时,请记住,在其他模块中,甚至在同一模块的src/main/res
中,也会添加资源目录。因此,使用附加分配(+=
)的重要性在于不要用新分配覆盖所有现有资源。
被声明为数组元素的路径是包含资源类型的路径,也就是说,资源类型是res文件夹通常包含的所有子目录,例如如颜色,可绘制,布局,值等。可以更改res文件夹的名称。
一个示例是使用路径"src/flavor/res/values/strings-ES"
,但是请注意,实践层次结构必须具有子目录values
:
├── module
├── flavor
├── res
├── values
├── strings-ES
├── values
├── strings.xml
├── strings.xml
该框架准确地按类型识别资源,这就是为什么不能省略通常已知的子目录的原因。
还请记住,flavor中的所有strings.xml
文件都将形成一个并集,以便无法复制资源。然后,以这种形式形成文件的并集在模块主模块之前具有更高的优先级。
flavor {
res.srcDirs += [
"src/flavor/res/values/strings-ES"
]
}
将strings-ES
目录视为包含资源类型的自定义资源。
GL