首页 文章

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

提问于
浏览
484

现在,我将每个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布局弹出窗口 . 菜单 .

18 回答

  • 11

    虽然多个资源集的所有提议都可以使用,但问题是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/提交了一个补丁,试图帮助解决问题 .

  • 2

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

    buying_bought_tracks.xml
    buying_buy_tracks.xml
    playing_edit_playlist.xml
    playing_play_playlist.xml
    playing_show_playlists.xml
    
  • 5

    如果您在批准的答案中使用该方法,并希望稍微改进它,那么更改gradle设置如下:

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

    因此,如果您添加更多文件夹和布局,则无需返回此处并附加一长串源文件夹,让gradle为您获取所有文件夹 .

  • 425

    嗯,简短的回答是否定的 . 但你绝对可以拥有多个 res 文件夹 . 我认为,这与 layout 文件夹的子文件夹一样接近 . Here's你是怎么做到的

  • 1

    小问题

    我可以按照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
    }
    

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


    如何使用

    对于这样的结构:

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

    希望能帮助到你!

  • 3

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

    您可以安装“Android文件分组”插件

    视窗:

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

    苹果电脑:

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

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

  • 0

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

    在实践中怎么办?

    例如,我想为 layout 创建一个名为 activity 的子文件夹,在 resDirs 变量中添加一个字符串,如 layouts ,然后将布局xml文件放在 res\layouts\activity\layout\xxx.xml 中 .

    如果我想为 drawable 创建一个名为 selectors 的子文件夹,在 resDirs 变量中添加一个字符串,如 drawables ,那么可绘制的xml文件应放在 res\drawables\selectors\drawable\xxx.xml 中 .

    文件夹名称如 layoutsdrawablesresDirs 变量中定义,它可以是任何字符串 . 您创建的所有子文件夹(如 activityselectors )都被视为与 res 文件夹相同 . 因此,在 selectors 文件夹中,我们必须另外创建 drawable 文件夹并将xml文件放在 drawable 文件夹中,之后该gradle可以将xml文件正常识别为可绘制文件 .

  • 0

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

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

    example folder structure

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

  • 71

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

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

    配置是这样的:

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

    检查documentation .

  • 9

    我只是想为那些遇到麻烦的人添加eskis的精彩答案 . (注意:这只会工作,看起来像'项目'视图中的单独目录,不幸的是不是'android'视图 . )

    经过以下测试 . BuildToolsVersion = 23.0.0 gradle 1.2.3和1.3.0

    这就是我使用已经建成的项目的方法 .

    • 从布局目录中复制所有XML文件,并将它们放入桌面上的目录或其他内容进行备份 .

    • 删除整个布局目录(确保从第1步支持所有内容!!!)

    • 右键单击res目录并选择new> directory .

    • 将此新目录命名为"layouts" . (这可以是你想要的任何东西,但它不会是'fragment'目录或'activity'目录,稍后会出现) .

    • 右键单击新的"layouts"目录,然后选择新建>目录 . (这将是您将在其中包含的XML文件类型的名称,例如,'fragments'和'activities') .

    • 右键单击'fragment'或'activities'目录(注意:这不是't have to be '片段' or '活动' that'只是我'm using as an example) and select new > directory once again and name this directory 328375 . (Note: This MUST be named '布局'!!!非常重要) .

    • 将您想要的XML文件放在您在桌面上创建的备份中的新'layout'目录中 .

    • 根据需要对任意数量的自定义目录重复步骤5 - 7 .

    • 一旦完成,进入你的模块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'
                    ]
        }
    }
    
    • 利润$$$$

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

    图片不仅仅是文字 .

    Directory Structure

  • 19
    • 步骤1:右键单击布局 - 在资源管理器中显示

    • 步骤2:打开布局文件夹并直接创建子文件夹:layout_1,layout_2 ...

    • 步骤3:打开layout_1创建文件夹布局(注意:强制名称是布局),打开layout_2文件夹创建布局子目录(注意:强制名称是布局)...

    • 步骤4:将xml文件复制到layout_1和layout_2中的布局子目录中

    • 步骤5:在buid.grade(模块应用程序)中运行代码并立即启用同步:


    sourceSets {
        main {
            res.srcDirs =
                [
                    'src / main / res / layout / layout_1'
                    'src / main / res / layout / layout_2',
                    'src / main / res'
                ]
        }
    }
    
    • 步骤6:摘要:上述所有步骤仅帮助群集文件夹并以'project'模式显示,而'android'模式将正常显示 .

    • 所以我画的可能是命名前缀和聚类文件夹一样有效 .

  • 3

    热门答案有几个缺点:您必须添加新的布局路径,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/ . 要创建子文件夹,您应使用此菜单:新建>文件夹> Res文件夹 .

    UPDATE

    几周后,我发现Android Studio没有注意到资源的变化 . 所以,出现了一些奇怪的错误 . 例如,布局继续显示旧尺寸,边距 . 有时AS找不到新的XML文件(特别是在运行时) . 有时它会混合 view id (对另一个XML文件的引用) . 通常需要按 Build > Clean ProjectBuild > Rebuild Project . 阅读Rebuild required after changing xml layout files in Android Studio .

  • 16

    你可以用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'
            ]
        }
    }
    

    nested resources picture

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

  • 228

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

    看看这个链接

    Android File Grouping

    enter image description here

  • 18

    如果您正在使用Linux或Mac机箱进行开发,那么解决方法就是创建子文件夹,其中包含指向布局文件的符号链接 . 只需使用带-s的ln命令即可

    ln -s PATH_TO_YOUR_FILE

    问题是,您的布局文件夹仍包含所有.xml文件 . 但您可以使用子文件夹选择它们 . 这是你最想要的东西 .

    我刚才读到,如果您使用的是Vista或更高版本,这也适用于Windows . 有这个 mklink 命令 . 只是谷歌,从来没有用过它 .

    另一个问题是,如果您打开文件并尝试再次打开它,插件会抛出一个NULL指针异常 . 但它并没有挂断 .

  • 4

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

  • 52

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

  • 3

    答案是不 .

    我想提请你注意这本书Pro Android 2,其中指出:

    值得注意的是有关资源的一些限制 . 首先,Android仅支持res下预定义文件夹中的线性文件列表 . 例如,它不支持布局文件夹下的嵌套文件夹(或res下的其他文件夹) . 其次,资产文件夹和res下的原始文件夹之间有一些相似之处 . 两个文件夹都可以包含原始文件,但raw中的文件被视为资源,而资产中的文件则不是 . 请注意,由于assets文件夹的内容不被视为资源,因此您可以在其中放置任意层次的文件夹和文件 .

相关问题