539

在 Android SDK 文档中,与 @drawable/my_image xml 语法一起使用的所有示例都直接针对存储在我项目的 res/drawable 目录中的图像。

我想知道在可绘制目录中创建子目录是否明确不行。

例如,如果我有以下目录布局:

res/drawable
-- sandwiches
  -- tunaOnRye.png
  -- hamAndSwiss.png
-- drinks
  -- coldOne.png
  -- hotTea.png

我可以将金枪鱼沙拉三明治的图像引用为@drawable/sandwiches/tunaOnRye

或者我是否必须在可绘制目录中保持层次结构平坦。

4

22 回答 22

577

不,资源机制不支持可绘制目录中的子文件夹,所以是的 - 您需要保持该层次结构平坦。

您显示的目录布局将导致没有可用的图像。

从我自己的实验看来,在文件夹内有一个包含任何项目的子res/drawable文件夹会导致资源编译器失败——阻止R.java正确生成文件。

于 2009-07-03T11:37:26.093 回答
158

我正在使用的解决方法(Android 本身似乎更喜欢)基本上是用下划线代替正斜杠,所以你的结构看起来像这样:

sandwich_tunaOnRye.png
sandwich_hamAndSwiss.png
drink_coldOne.png
drink_hotTea.png

该方法要求您在命名时一丝不苟,并且不会使文件本身更容易争吵(如果您决定饮料和三明治真的应该都是“ food”,那么您必须进行大规模重命名而不是简单地将它们移动到目录);但是与等效的文件夹结构相比,您的编程逻辑的复杂性并没有受到太大影响。

这种情况确实很糟糕。Android 是一个混合了美妙而糟糕的设计决策的包。我们只能希望后一部分尽快被淘汰:)

于 2011-02-03T17:57:18.727 回答
41

实际上,在 Android Studio 上是可能的。您可以拥有如下所示的嵌套资源

在此处输入图像描述

这里还有一个对资源进行分组的插件。

我建议避免这种情况。

于 2015-08-14T10:45:15.337 回答
35

是的 - 它确实很烂:) 但是您可以使用资产文件夹并在其中有子目录并以这种方式加载图像。

于 2010-10-07T09:37:31.670 回答
23

使用资产文件夹。

示例代码:

InputStream is = null;
try {
    is = this.getResources().getAssets().open("test/sample.png");
} catch (IOException e) {
    ;
}

image = BitmapFactory.decodeStream(is);
于 2011-05-12T03:36:39.363 回答
22

我写了一个 eclipse 插件,它允许通过用两个下划线分隔文件名来创建虚拟子文件夹__。该项目处于早期阶段,但不要担心它不会使您的 IDE 崩溃

可以在此处找到更多详细信息,请随时分叉并发送拉取请求:

https://github.com/kirill578/Android-Sorted-Res-Folder

在此处输入图像描述

于 2014-05-03T15:29:07.330 回答
9

在带有 gradle 的 android studio 中,您可以拥有多个源控制器,这将允许您分离资源。例如:

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

但是,名称不能冲突,这意味着您仍然需要使用诸如 Sandwiches_tunaOnRye 之类的名称,但您可以为所有三明治设置一个单独的部分。

这允许您将资源存储在不同的结构中(对于自动生成的内容很有用,例如 actionbargenerator)

于 2014-10-03T08:54:22.480 回答
9

我喜欢使用一个简单的脚本将设计师提供的有组织的目录结构展平为可用于生成 R 文件的东西。

在 drawable-hdpi 中使用当前路径运行:

#! /bin/bash
DIRS=`find * -type d`
for dir in ${DIRS} ; do 
  for file in `ls ${dir}` ; do
    mv ${dir}/${file}  ${dir}_${file};
  done 
  rmdir ${dir};
done
于 2011-11-30T10:54:53.633 回答
5

部分解决该问题的一种方法是使用 API 级别后缀。我使用 res/layout-v1、res/layout-v2 等在同一个 apk 中保存多个子项目。此机制可用于所有资源类型。

显然,这只能在您的目标 API 级别高于 res/layout-v 时使用?您正在使用。

此外,请注意 Android 1.5 和 1.6 中的错误。 请参阅有关 API 级别后缀的 Andoroid 文档

于 2010-11-27T09:24:14.370 回答
4

随着图书馆系统的出现,为每个大型资产集创建一个图书馆可能是一种解决方案。

这仍然是一个问题,因为必须避免在所有资产中使用相同的名称,但每个库使用前缀方案应该有助于解决这个问题。

它不像能够创建文件夹那么简单,但这有助于保持理智......

于 2012-08-20T01:42:15.413 回答
3

这种情况有一个解决方法:您可以resVector在与默认文件夹相同的级别上创建一个(例如)文件res夹。您可以在drawable-xxx那里添加任何资源文件夹:

resVector
-drawable
-layout
-color

之后,您只需要添加

sourceSets {
        main.res.srcDirs += 'src/main/resVector'
    }

进入您的build.gradle文件(内部android { })。

于 2017-04-07T12:08:15.723 回答
1

这不是完美的方法。您必须实现与 display here相同的方式。

也可以通过可以使用的代码调用文件夹下的图片

Resources res = getResources();
Drawable shape = res. getDrawable(R.drawable.gradient_box);

TextView tv = (TextView)findViewByID(R.id.textview);
tv.setBackground(shape);
于 2014-01-09T14:39:45.767 回答
1

不是我的,但我在寻找这个问题时发现了这个线程,如果你使用 Android Studio 和 Gradle Build 系统,它很容易不需要插件,只需编辑一点构建文件

https://stackoverflow.com/a/22426467/618419

于 2014-05-09T18:29:23.340 回答
1

带有 Android Studio 的 Gradle 可以这样做(链接)。

它在“配置结构”段落中

sourceSets {
 main {
    java {
        srcDir 'src/java'
    }
    resources {
        srcDir 'src/resources'
    }
 }
}
于 2015-07-30T07:46:51.153 回答
1

在 main 中创建一个文件夹。像:'res_notification_btn'

并在其中创建树文件夹,例如“drawable”或“layout”

然后在'build.gradle'中添加这个

sourceSets
            {
                main
                {
                    res
                    {
                        srcDirs = ['src/main/res_notification_btn', 'src/main/res']
                      or
                        srcDir 'src/main/res_notification_btn'
                    }
                }
            }
于 2017-03-29T06:43:12.933 回答
0

assets/ 您可以使用它来存储原始资产文件。您在此处保存的文件将按原样编译为 .apk 文件,并保留原始文件名。您可以使用 URI 以与典型文件系统相同的方式导航此目录,并使用 AssetManager 将文件作为字节流读取。例如,这是放置纹理和游戏数据的好位置。 http://developer.android.com/tools/projects/index.html

于 2014-06-01T17:24:47.720 回答
0
#!/usr/bin/env ruby

# current dir should be drawable-hdpi/ etc

# nuke all symlinks
Dir.foreach('.') {|f|
    File.delete(f) if File.symlink?(f)
}

# symlink all resources renaming with underscores
Dir.glob("**/*.png") {|f|
    system "ln -s #{f} #{f.gsub('/', '_')}" if f.include?("/")
}
于 2013-03-29T17:59:02.380 回答
0

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

于 2014-05-14T08:32:23.153 回答
0

不允许子目录,资源必须仅包含 [a-z0-9_.]。

不,你有大写字母,也没有正斜杠。

于 2015-09-13T09:04:05.983 回答
0

对于使用 Xamarin(Xamarin.Android 或 Xamarin.Forms)的任何人,有一种方法可以做到这一点。

在 Android 项目的 .csproj 文件中,找到 MonoAndroidResourcePrefix 的行(记录在案,虽然很差,但在这里)。在此处添加您要使用的子目录,用分号分隔每个条目。在构建时,Visual Studio 会去除这些前缀,以便所有资源最终都处于一个平面层次结构中。进行这些更改后,您可能需要重新加载解决方案。

Xamarin 中的设置示例

这些目录不需要是项目中默认 Resources 目录的子目录。

确保您添加的文件将构建操作设置为“AndroidResource”。

对于 Xamarin.Android,可视化编辑器无法识别图像并显示错误“无法解析此资源 URL”,但项目将生成并且图像将在运行时可见。

编辑器中的错误 模拟器中的示例

于 2022-01-28T21:13:29.007 回答
0

可以通过有一个与“res”平行的额外文件夹和一个子目录“drawable”来拥有多个可绘制文件夹,然后将以下内容添加到gradle:

sourceSets {
    main {
        res.srcDirs 'src/main/<extra_res>'
    }
}

使用 gradle 6.5.1 测试

于 2020-10-22T17:33:30.703 回答
-6
  1. 右键单击可绘制
  2. 选择新建--->目录
  3. 输入目录名称。例如:logo.png(该位置默认已经显示可绘制文件夹)
  4. 将图像直接复制并粘贴到可绘制文件夹中。粘贴时,您可以选择为列表中的每个图像选择 mdpi/xhdpi/xxhdpi 等。选择适当的选项并输入图像的名称。确保保持与目录名称相同的名称,即 logo.png
  5. 对其余图像执行相同操作。所有这些都将放在 logo.png 主文件夹下。
于 2018-10-10T10:45:24.437 回答