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

发布于 2024-10-16 12:27:42 字数 438 浏览 6 评论 0原文

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

Right now, I'm storing every XML layout file inside the 'res/layout' folder, so it is feasible and simple to manage small projects, but when there is a case of large and heavy projects, then there should be a hierarchy and sub-folders needed inside the layout folder.

for e.g.

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

Like the same way, we would like to have sub-folders for the large application, so is there any way to do so inside the Android project?

I am able to create layout-personal and layout_address sub-folders inside the layout folder, but when the time comes to access the XML layout file using R.layout._______ , at that time there is no any XML layout pop-up inside the menu.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(20

话少情深 2024-10-23 12:27:42

可以使用gradle来做到这一点。我制作了一个演示项目来展示如何操作。

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

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

下面是演示中 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 布局等)的直接父级仍然需要符合规范

You CAN do this with gradle. I've made a demo project showing how.

The trick is to use gradle's ability to merge multiple resource folders, and set the res folder as well as the nested subfolders in the sourceSets block.

The quirk is that you can't declare a container resource folder before you declare that folder's child resource folders.

Below is the sourceSets block from the build.gradle file from the demo. Notice that the subfolders are declared first.

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

nested resources picture

Also, the direct parent of your actual resource files (pngs, xml layouts, etc..) does still need to correspond with the specification.

我最亲爱的 2024-10-23 12:27:42

答案是否定的。

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

还有一些值得注意的地方
资源方面的限制。
首先,Android只支持线性
预定义的文件列表
res 下的文件夹。例如,它
不支持嵌套文件夹
布局文件夹
(或其他
res 下的文件夹)。

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

请注意,因为
不考虑 assets 文件夹
资源,你可以任意放置一个
文件夹和文件的层次结构
它。

The answer is no.

I would like to draw your attention towards this book Pro Android 2 that states:

It is also worth noting a few
constraints regarding resources.
First, Android supports only a linear
list of files within the predefined
folders under res. For example, it
does not support nested folders under
the layout folder
(or the other
folders under res).

Second, there are some similarities
between the assets folder and the raw
folder under res. Both folders can
contain raw files, but the files
within raw are considered resources
and the files within assets are not.

Note that because the contents of the
assets folder are not considered
resources, you can put an arbitrary
hierarchy of folders and files within

it.

悸初 2024-10-23 12:27:42

我只是想补充 eskis 为遇到麻烦的人提供的精彩答案。 (注意:这只能工作,并且看起来像“项目”视图中的单独目录,不幸的是,而不是“android”视图中的目录。)

使用以下内容进行了测试。
构建工具版本 = 23.0.0
gradle 1.2.3 & 1.3.0

这就是我如何让我的项目与已经构建的项目一起工作。

  1. 将所有 XML 文件从布局目录中复制出来,并将它们放入桌面上的目录或其他目录中以进行备份。
  2. 删除整个布局目录(确保您备份了步骤 1 中的所有内容!!!)
  3. 右键单击 res 目录并选择“新建”>“目录。
  4. 将这个新目录命名为“layouts”。 (这可以是您想要的任何目录,但它不会是稍后出现的“片段”目录或“活动”目录)。
  5. 右键单击新的“布局”目录并选择“新建”>“布局”目录。 (这将是其中包含的 XML 文件类型的名称,例如“片段”和“活动”)。
  6. 右键单击“fragment”或“activities”目录(注意:这不必是“fragment”或“activities”,这只是我用作示例的目录)并选择 new > >再次目录并将该目录命名为“layout”。 (注意:这必须命名为“布局”!!!非常重要)。
  7. 将所需的 XML 文件放入桌面上备份的新“布局”目录中。
  8. 根据需要对任意数量的自定义目录重复步骤 5 - 7。
  9. 完成后,进入模块 gradle.build 文件并创建一个像这样的 sourceSets 定义...(确保 'src/main/res/layouts' 和 'src/main/res' 始终是下面两个!!!就像我下面展示的那样)。

    源集{
        主要的 {
            res.srcDirs =
                    [
                            'src/main/res/layouts/activities',
                            'src/main/res/layouts/fragments',
                            'src/main/res/layouts/content',
                            'src/main/res/layouts',
                            'src/主/res'
                    ]
        }
    }
    
  10. 利润$$$$

但说真的..这就是我让它工作的方式。如果有人有任何疑问请告诉我..我可以尽力提供帮助。

图片比文字更有价值。

目录结构

I just wanted to add onto eskis' fantastic answer for people having trouble. (Note: This will only work and look like separate directories inside the 'project' view, not the 'android' view unfortunately.)

Tested with the following.
BuildToolsVersion = 23.0.0
gradle 1.2.3 & 1.3.0

This is how I got mine to work with an already built project.

  1. Copy all of the XML files out of your layout directory, and put them into a directory on the desktop or something for backup.
  2. Delete the entire layout directory (Make sure you backed everything up from step 1!!!)
  3. Right click the res directory and select new > directory.
  4. Name this new directory "layouts". (This can be whatever you want, but it will not be a 'fragment' directory or 'activity' directory, that comes later).
  5. Right click the new "layouts" directory and select new > directory. (This will be the name of the type of XML files you will have in it, for example, 'fragments' and 'activities').
  6. Right click the 'fragment' or 'activities' directory (Note: this doesn't have to be 'fragment' or 'activities' that's just what i'm using as an example) and select new > directory once again and name this directory "layout". (Note: This MUST be named 'layout'!!! very important).
  7. Put the XML files you want inside the new 'layout' directory from the backup you made on your desktop.
  8. Repeat steps 5 - 7 for as many custom directories as you desire.
  9. Once this is complete, go into your modules gradle.build file and create a sourceSets definition like this...(Make sure 'src/main/res/layouts' & 'src/main/res' are always the bottom two!!!! Like I am showing below).

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

But seriously.. this is how I got it to work. Let me know if anyone has any questions.. I can try to help.

Pictures are worth more than words.

Directory Structure

装纯掩盖桑 2024-10-23 12:27:42

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

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

Not possible, but the layout folder is sorted by name. So, I prepend the layout file names with my package names. E.g. for the two packages "buying" and "playing":

buying_bought_tracks.xml
buying_buy_tracks.xml
playing_edit_playlist.xml
playing_play_playlist.xml
playing_show_playlists.xml
白况 2024-10-23 12:27:42

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

安装“Android文件分组”插件

您可以通过Windows

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

苹果:

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

对于 Mac,我能够测试它,但无法搜索该插件。因此,我从此处下载了该插件,并使用了从磁盘安装插件<上述设置中的 /code> 选项。

I use Android File Grouping plugin for Android Studio.It doesn't really allows you to create sub-folders, but it can DISPLAY your files and resources AS they are in different folders. And this is exactly what I wanted.

You can install "Android File Grouping" plugin by

Windows:

Android Studio -> File -> Settings -> Plugins.

Mac:

Android Studio -> Android Studio Tab (Top Left) -> Preferences -> Plugins -> Install JetBrains Plugin..

For Mac, I was able to test it and was not able to search for the plugin. So I downloaded the plugin from here and used the Install plugin from disk option from the above setting.

天生の放荡 2024-10-23 12:27:42

小问题

我可以通过遵循此问题的最佳答案来实现子文件夹。

然而,随着项目变得越来越大,您将拥有许多子文件夹:

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() 采用 相对路径 作为参数。 相对路径是相对于项目根目录的。因此,当我们输入 "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
}

希望有帮助!

Small Problem

I am able to achieve subfolders by following the top answer to this question.

However, as the project grows bigger, you will have many sub-folders:

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

Not a big problem, but:

  • It's not pretty as the list become very long.
  • You have to change your app/build.gradle everytime you add a new folder.

Improvement

So I wrote a simple Groovy method to grab all nested folders:

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
}

Paste this method outside of the android {...} block in your app/build.gradle.


How to use

For a structure like this:

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

Use it like this:

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

If you have a structure like this:

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

You will use it like this:

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

Explanation

getLayoutList() takes a relative path as an argument. The relative path is relative to the root of the project. So when we input "app/src/main/res/layouts/", it will return all the subfolders' name as an array, which will be exactly the same as:

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

Here's the script with comments for understanding:

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
}

Hope it helps!

厌倦 2024-10-23 12:27:42

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

I think the most elegant solution to this problem (given that subfolders are not allowed) is to prepend the file names with the name of the folder you would have placed it inside of. For example, if you have a bunch of layouts for an Activity, Fragment, or just general view called "places" then you should just prepend it with places_my_layout_name. At least this solves the problem of organizing them in a way that they are easier to find within the IDE. It's not the most awesome solution, but it's better than nothing.

灵芸 2024-10-23 12:27:42

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

它不完全是一个子文件夹,但可能分隔应用程序的各个部分。

配置是这样的:

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

查看文档

Now with Android Studio and Gradle, you can have multiple resource folders in your project. Allowing to organize not only your layout files but any kind of resources.

It's not exactly a sub-folder, but may separte parts of your application.

The configuration is like this:

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

Check the documentation.

您的好友蓝忘机已上羡 2024-10-23 12:27:42

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

来查看此链接

Android 文件分组

在此处输入图像描述

Now we can easily do with JetBrains plugin called "Android File Grouping"

check out this link

Android File Grouping

enter image description here

蓝咒 2024-10-23 12:27:42

我这样做的一种方法是创建一个单独的 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 文件之前添加相关子文件夹)。

A way i did it was to create a separate res folder at the same level as the actual res folder in your project, then you can use this in your apps build.gradle

android {
    //other stuff

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

example folder structure

then each subfolder of your new res folder can be something relating to each particular screen or something in your app, and each folder will have their own layout / drawable / values etc keeping things organised and you dont have to update the gradle file manually like some of these other answers require (Just sync your gradle each time you add a new resource folder so it knows about it, and make sure to add the relevant subfolders before adding your xml files).

笑饮青盏花 2024-10-23 12:27:42

检查将文件夹层次结构转换为单个文件夹的 Bash 展平文件夹脚本

Check Bash Flatten Folder script that converts folder hierarchy to a single folder

彼岸花ソ最美的依靠 2024-10-23 12:27:42

如果您使用已批准答案中的方法,并且想要对其进行一些改进,请像这样更改 gradle 设置:

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

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

If you use the method in the approved answer, and want to improve it on a bit, then change the gradle setting like this:

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

So if you add more folders and layouts, you don't need to come back here and append a long list of source folders, let gradle get all the folders for you.

自此以后,行同陌路 2024-10-23 12:27:42

如果您正在 Linux 或 Mac 上进行开发,解决方法是创建包含布局文件符号链接的子文件夹。只需使用带有 -s 的 ln 命令

ln -s PATH_TO_YOUR_FILE

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

我刚刚读到,如果您使用的是 Vista 或更高版本,这也可能适用于 Windows。有这个mklink命令。 google了一下,自己没用过。

另一个问题是,如果您打开了文件并尝试再次打开它,插件会抛出空指针异常。但它不会挂断。

If you are developing on a linux or a mac box, a workaround would be, to create subfolders which include symbolic links to your layoutfiles. Just use the ln command with -s

ln -s PATH_TO_YOUR_FILE

The Problem with this is, that your Layout folder still contains all the .xml files. But you could although select them by using the sub-folders. It's the closest thing, to what you would like to have.

I just read, that this might work with Windows, too if you are using Vista or later. There is this mklink command. Just google it, have never used it myself.

Another problem is, if you have the file opened and try to open it again out the plugin throws a NULL Pointer Exception. But it does not hang up.

别闹i 2024-10-23 12:27:42

虽然针对多个资源集的所有建议都可能有效,但问题是 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/ 尝试帮助解决问题。

While all the proposals for multiple resource sets may work, the problem is that the current logic for the Android Studio Gradle plug-in will not update the resource files after they have changed for nested resource sets. The current implementation attempts to check the resource directories using startsWith(), so a directory structure that is nested (i.e. src/main/res/layout/layouts and src/main/res/layout/layouts_category2) will choose src/main/res/layout/layouts consistently and never actually update the changes. The end result is that you have to rebuild/clean the project each time.

I submitted a patch at https://android-review.googlesource.com/#/c/157971/ to try to help resolve things.

何以笙箫默 2024-10-23 12:27:42

@eski 的最佳答案很好,但是代码使用起来并不优雅,所以我在 gradle 中编写了一个 groovy 脚本以供一般使用。它适用于所有构建类型和产品风格,不仅可以用于布局,您还可以为任何其他资源类型(例如可绘制资源)添加子文件夹。代码如下(放在项目级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< /code>,那么布局xml文件应该放在res\layouts\activity\layout\xxx.xml中。

如果我想为 drawable 创建名为 selectors 的子文件夹,请在 resDirs 变量中添加任意名称的字符串,例如 drawables >,那么drawable xml文件应该放在res\drawables\selectors\drawable\xxx.xml中。

layoutsdrawables 等文件夹名称定义在 resDirs 变量中,可以是任何字符串。
您创建的所有子文件夹(例如 activityselectors)都被视为与 res 文件夹相同。所以在selectors文件夹中,我们必须另外创建drawable文件夹,并将xml文件放入drawable文件夹中,之后gradle才能将xml文件识别为drawable通常情况下。

The top answer by @eski is good, but the code is not elegant to use, so I wrote a groovy script in gradle for general use. It's applied to all build type and product flavor and not only can be use for layout, you can also add subfolder for any other resources type such as drawable. Here is the code(put it in android block of project-level gradle file):

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

How to do in practice?

For example, I want to create subfolder named activity for layout, add a string by any name in resDirs variable such as layouts, then the layout xml file should be put in res\layouts\activity\layout\xxx.xml.

If I want to create subfolder named selectors for drawable, add a string by any name in resDirs variable such as drawables, then the drawable xml file should be put in res\drawables\selectors\drawable\xxx.xml.

The folder name such as layouts and drawables is defined in resDirs variable, it can be any string.
All subfolder created by you such as activity or selectors are regarded as the same as res folder. So in selectors folder, we must create drawable folder additionally and put xml files in drawable folder, after that gradle can recognize the xml files as drawable normally.

⒈起吃苦の倖褔 2024-10-23 12:27:42
  • 步骤一:右键layout-show in explorer
  • 步骤二:打开layout文件夹,直接创建子文件夹:layout_1,layout_2 ...
  • 步骤三:打开layout_1创建文件夹layout(注意:强制名称为layout),打开layout_2文件夹创建布局子目录(注意:强制名称为layout)...
  • 第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”模式将正常显示。
  • 所以我认为命名前缀可能和集群文件夹一样有效。
  • Step 1: Right click on layout - show in explorer
  • Step 2: Open the layout folder and create the subfolders directly: layout_1, layout_2 ...
  • Step 3: open layout_1 create folder layout (note: mandatory name is layout), open layout_2 folder create layout subdirectory (note: mandatory name is layout) ...
  • Step 4: Copy the xml files into the layout subdirectories in layout_1 and layout_2
  • Step 5: Run the code in buid.grade (module app) and hit sync now:

sourceSets {
    main {
        res.srcDirs =
            [
                'src / main / res / layout / layout_1'
                'src / main / res / layout / layout_2',
                'src / main / res'
            ]
    }
}
  • Step 6: Summary: All the steps above will only help clustering folders and display in 'project' mode, while 'android' mode will display as normal.
  • So I draw that maybe naming prefixes is as effective as clustering folders.
×纯※雪 2024-10-23 12:27:42

不能有子目录(很容易),但您可以有其他资源文件夹。令人惊讶的是没有人提到它,但要保留默认资源文件夹,并添加更多内容:

    sourceSets {
        main.res.srcDirs += ['src/main/java/XYZ/ABC']
    }

Cannot have subdirectories (easily) but you can have additional resource folders. Surprised no one mentioned it already, but to keep the default resource folders, and add some more:

    sourceSets {
        main.res.srcDirs += ['src/main/java/XYZ/ABC']
    }
滥情哥ㄟ 2024-10-23 12:27:42

嗯,简短的回答是否定的。但您绝对可以拥有多个 res 文件夹。我认为,这与 layout 文件夹的子文件夹是最接近的。 这是具体操作方法。

Well, the short answer is no. But you definitely can have multiple res folders. That, I think, is as close as you can get to having subfolders for the layout folder. Here's how you do it.

余罪 2024-10-23 12:27:42

最佳答案有几个缺点:您必须添加新的布局路径,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/。为了创建子文件夹,您应该使用此菜单:“新建”>“子文件夹”。文件夹>资源文件夹。

更新

几周后,我发现Android Studio 没有注意到资源的变化。因此,一些奇怪的错误出现了。例如,布局继续显示旧的尺寸、边距。有时 AS 找不到新的 XML 文件(尤其是在运行时)。有时它会混合视图 ID(对另一个 XML 文件的引用)。通常需要按 Build > 。清理项目构建>重建项目。阅读 在 Android Studio 中更改 xml 布局文件后需要重新构建< /a>.

Top answers have several disadvantages: you have to add new layout paths, AS places new resources to res\layouts folder instead of res\values.

Combining several answers I wrote similar:

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

I made folders with this article: http://alexzh.com/tutorials/how-to-store-layouts-in-different-folders-in-android-project/. In order to create subfolders you should use this menu: New > Folder > Res Folder.

UPDATE

After a couple of weeks I found that changes in resources are not noticed by Android Studio. So, some weird bugs appear. For instance, layouts continue to show old sizes, margins. Sometimes AS doesn't find new XML-files (especially during run-time). Sometimes it mixes view ids (references to another XML-file). It's often required to press Build > Clean Project or Build > Rebuild Project. Read Rebuild required after changing xml layout files in Android Studio.

跨年 2024-10-23 12:27:42

在模块内,要拥有风味、风味资源(布局、值)和风味资源资源的组合,需要记住的主要事情有两点:

  1. res.srcDirs 中添加资源目录时+=) 非常重要,以免新分配覆盖所有现有资源。

  2. 声明为数组元素的路径是包含资源类型的路径,即资源类型是 res 文件夹通常包含的所有子目录,例如 颜色、drawable、布局、值等。res文件夹的名称可以更改。

一个例子是使用路径“src/flavor/res/values/strings-ES”,但注意实践层次结构必须具有子目录values

├── module 
   ├── flavor
      ├── res
         ├── values
            ├── strings-ES
               ├── values
                  ├── strings.xml
               ├── strings.xml
 

框架按类型精确识别资源,这就是为什么通常已知的子目录不能被省略。

另请记住,风味内的所有 strings.xml 文件将形成一个联合,以便资源无法重复。反过来,在风味中形成文件的联合在模块的主文件之前具有更高的优先级。

flavor {
        res.srcDirs += [
            "src/flavor/res/values/strings-ES"
        ]
}

将 string-ES 目录视为包含资源类型的自定义资源。

GL

Within a module, to have a combination of flavors, flavor resources (layout, values) and flavors resource resources, the main thing to keep in mind are two things:

  1. When adding resource directories in res.srcDirs for flavor, keep in mind that in other modules and even in src/main/res of the same module, resource directories are also added. Hence, the importance of using an add-on assignment (+=) so as not to overwrite all existing resources with the new assignment.

  2. The path that is declared as an element of the array is the one that contains the resource types, that is, the resource types are all the subdirectories that a res folder contains normally such as color, drawable, layout, values, etc. The name of the res folder can be changed.

An example would be to use the path "src/flavor/res/values/strings-ES" but observe that the practice hierarchy has to have the subdirectory values:

├── module 
   ├── flavor
      ├── res
         ├── values
            ├── strings-ES
               ├── values
                  ├── strings.xml
               ├── strings.xml
 

The framework recognizes resources precisely by type, that is why normally known subdirectories cannot be omitted.

Also keep in mind that all the strings.xml files that are inside the flavor would form a union so that resources cannot be duplicated. And in turn this union that forms a file in the flavor has a higher order of precedence before the main of the module.

flavor {
        res.srcDirs += [
            "src/flavor/res/values/strings-ES"
        ]
}

Consider the strings-ES directory as a custom-res which contains the resource types.

GL

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文