Android Layout文件夹可以包含子文件夹吗?

Par*_*ani 528 android android-layout

现在,我将每个xml布局文件存储在res/layout文件夹中,因此管理小项目是可行且简单的,但是当存在大型和重型项目的情况时,则应该存在层次结构和子文件夹布局文件夹.

例如

layout
-- layout_personal
   -- personal_detail.xml
   -- personal_other.xml
--layout_address
  -- address1.xml
  -- address2.xml
Run Code Online (Sandbox Code Playgroud)

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

我可以在布局文件夹中创建layout-personal和layout_address子文件夹,但是当使用R.layout ._______访问xml布局文件的时候,当时内部没有任何xml布局弹出窗口.菜单.

esk*_*ski 463

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

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

问题是,在声明该文件夹的子资源文件夹之前,您无法声明容器资源文件夹.

下面是demo中build.gradle文件中的sourceSets块.请注意,首先声明子文件夹.

sourceSets {
    main {
        res.srcDirs =
        [
                'src/main/res/layouts/layouts_category2',
                'src/main/res/layouts',
                'src/main/res'
        ]
    }
}
Run Code Online (Sandbox Code Playgroud)

嵌套资源图片

此外,实际资源文件的直接父级(png,xml布局等)仍然需要与规范相对应.

  • 这是有效的,但答案确实是一个_jefullyfully_不足以解释你添加的每个子文件夹都需要在其中有一个_second_子文件夹,它只能被称为"布局",并且所有的布局文件都需要进入_second_子文件夹.通过阅读数十条评论来解决这个问题远非理想.对于任何仍在寻找的人来说,设置额外的"布局"子文件夹是"URI未注册"问题的解决方案. (25认同)
  • 太好了!请记住,你真的只是利用gradle的*合并*资源文件夹的能力,它才有意义. (7认同)
  • 是否可以使用drawable文件夹执行此操作?我只是试着没有运气,甚至考虑到声明的排序. (6认同)
  • 文件夹中的文件名仍然必须是唯一的,在代码中您必须知道例如`R.layout.list_item`来自`movies`或`cinemas`文件夹,因此平面命名仍然适用. (5认同)
  • 不幸的是,使用`build:gradle:0.14.4`和`buildToolsVersion"21.1.1"`这对我不起作用. (5认同)
  • 嘿伙计们,我读了上面的所有评论.但是,我正面临另一个问题.我在res/layout文件夹中创建了一个目录,并在子目录中创建了一个新的布局.我的新目录结构:-res/layout/fragment_layouts我也做了build.gradle的东西.我在fragment_layouts文件夹中创建了一个名为my_frag_layout.xml的布局.但是,当我尝试在my_frag_layout.xml中声明android命名空间时,我不断收到消息:URI未注册.有人可以帮我解决这个问题吗?请帮忙! (4认同)
  • 这显示我的每个xml中都有"URI未注册". (3认同)
  • as @ user3509153我在包含"http://schemas.android.com/apk/res/android"的行的每个布局中也收到错误"URI not registered".有什么想法解决这个问题? (2认同)

100*_*abh 231

答案是不.

我想提请你注意本书Pro Android 2:

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

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

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

  • @Justin查看我发布的用于gradle的解决方案. (15认同)
  • 我邀请我们的下一个最好的希望是Eclipse或IntelliJ插件,它可以根据文件名前缀折叠文件. (3认同)
  • 问题不是“他应该这样做”,而是“他能这样做吗”,因此您的答案与该问题无关。这只是对过程的意见。对、错或无所谓,你没有提供问题的答案,所以不确定你是如何获得如此多的赞成票的。 (3认同)

hit*_*ted 76

我只想为有问题的人添加eskis的精彩答案.(注意:这只会起作用,看起来像'项目'视图中的单独目录,不幸的是不是'android'视图.)

测试如下.BuildToolsVersion = 23.0.0 gradle 1.2.3和1.3.0

这就是我如何使用已经建成的项目.

  1. 将所有XML文件复制到布局目录之外,并将它们放入桌面上的目录或其他内容进行备份.
  2. 删除整个布局目录(确保从步骤1支持所有内容!!!)
  3. 右键单击res目录并选择new> directory.
  4. 将此新目录命名为"layouts".(这可以是你想要的任何东西,但它不会是'片段'目录或'活动'目录,稍后会出现).
  5. 右键单击新的"layouts"目录并选择new> directory.(这将是您将在其中包含的XML文件类型的名称,例如,"片段"和"活动").
  6. 右键单击'fragment'或'activities'目录(注意:这不一定是'fragment'或'activities',这就是我正在使用的例子)并再次选择new> directory并命名这个目录"布局".(注意:这必须命名为'layout'!!!非常重要).
  7. 将您想要的XML文件放在您在桌面上创建的备份中的新"布局"目录中.
  8. 根据需要为任意数量的自定义目录重复步骤5 - 7.
  9. 完成后,进入你的模块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'
                    ]
        }
    }
    
    Run Code Online (Sandbox Code Playgroud)
  10. 利润★

但是说真的..这就是我开始工作的方式.如果有人有任何问题,请告诉我.我可以尝试提供帮助.

图片不仅仅是文字.

目录结构

  • 我没有测试它,但我想你只是在布局文件夹旁边创建一个layout-v21文件夹. (4认同)
  • 我遇到了这个http://stackoverflow.com/questions/41934004/android-studio-uri-is-not-registered-after-grouping-layouts-into-subdirectory的问题 (3认同)
  • 搜索了一段时间没有运气,这是唯一对我有用的解决方案.感谢您用图片发布这样详细的答案! (2认同)

小智 52

不可能,但布局文件夹按名称排序.所以,我在布局文件名前加上我的包名.例如,两个包"购买"和"玩":

buying_bought_tracks.xml
buying_buy_tracks.xml
playing_edit_playlist.xml
playing_play_playlist.xml
playing_show_playlists.xml
Run Code Online (Sandbox Code Playgroud)


小智 20

我为Android Studio 使用Android文件分组插件.它实际上不允许您创建子文件夹,但它可以显示您的文件和资源,因为它们位于不同的文件夹中.这正是我想要的.

您可以安装"Android文件分组"插件

视窗:

Android Studio - >文件 - >设置 - >插件.

苹果电脑:

Android Studio - > Android Studio标签(左上角) - >首选项 - >插件 - >安装JetBrains插件..

对于Mac,我能够测试它并且无法搜索插件.所以我从这里下载了插件并使用Install plugin from disk了上面设置中的选项.

  • 该插件无法在"Android"视图上运行,只有"Project"视图:/ (2认同)

And*_*son 18

现在使用Android Studio和Gradle,您可以在项目中拥有多个资源文件夹.允许不仅组织您的布局文件,还组织任何类型的资源.

它不完全是一个子文件夹,但可以分离您的应用程序的一部分.

配置是这样的:

sourceSets {
    main {
        res.srcDirs = ['src/main/res', 'src/main/res2']
    }
}
Run Code Online (Sandbox Code Playgroud)

查看文档.

  • 我注意到每次我在这个设置下对布局进行更改时,我总是不得不做一个`clean`来看它反映在app上. (2认同)

bot*_*bot 16

我认为这个问题最优雅的解决方案(假设不允许使用子文件夹)是在文件名前加上你将它放在里面的文件夹的名称.例如,如果您有一堆Activity,Fragment或只是名为"places"的一般视图的布局,那么您应该只使用places_my_layout_name作为前缀.至少这解决了以在IDE中更容易找到的方式组织它们的问题.这不是最棒的解决方案,但它总比没有好.


I'm*_*gon 15

小问题

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

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

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'
            ]
    }
}
Run Code Online (Sandbox Code Playgroud)

不是一个大问题,但是:

  • 因为列表变得很长,所以它并不漂亮.
  • 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
}
Run Code Online (Sandbox Code Playgroud)

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


如何使用

对于这样的结构:

<project root>
??? app <---------- TAKE NOTE
??? build
??? build.gradle
??? gradle
??? gradle.properties
??? gradlew
??? gradlew.bat
??? local.properties
??? settings.gradle
Run Code Online (Sandbox Code Playgroud)

像这样使用它:

android {
    sourceSets {
        main {
            res.srcDirs = getLayoutList("app/src/main/res/layouts/")
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

如果你有这样的结构:

<project root>
??? my_special_app_name <---------- TAKE NOTE
??? build
??? build.gradle
??? gradle
??? gradle.properties
??? gradlew
??? gradlew.bat
??? local.properties
??? settings.gradle
Run Code Online (Sandbox Code Playgroud)

你会像这样使用它:

android {
    sourceSets {
        main {
            res.srcDirs = getLayoutList("my_special_app_name/src/main/res/layouts/")
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

说明

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'
            ]
Run Code Online (Sandbox Code Playgroud)

这是带有注释以理解的脚本:

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
}
Run Code Online (Sandbox Code Playgroud)

希望能帮助到你!


Bha*_*ina 15

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

看看这个链接

Android文件分组

在此输入图像描述

  • 不应该是公认的答案,因为它在 Android 视图中不起作用......(但我喜欢这个想法^^) (3认同)
  • 这对最后一个版本的 android 不起作用......是否有更新版本? (2认同)

Fon*_*nix 6

我这样做的方法是在与项目中的实际res文件夹相同的级别创建一个单独的res文件夹,然后你可以在你的应用程序build.gradle中使用它.

android {
    //other stuff

    sourceSets {
        main.res.srcDirs = ['src/main/res', file('src/main/layouts').listFiles()]
    }
}
Run Code Online (Sandbox Code Playgroud)

示例文件夹结构

然后你的新res文件夹的每个子文件夹可以是与你的应用程序中的每个特定屏幕或某些东西相关的东西,并且每个文件夹都有自己的layout/ drawable/ valuesetc保持组织的东西,你不必像其他一些手动更新gradle文件答案要求(每次添加新的资源文件夹时都要同步你的gradle,以便它知道它,并确保在添加xml文件之前添加相关的子文件夹).