Может ли каталог для рисования Android содержать подкаталоги?


497

В документации по Android SDK все примеры, используемые с синтаксисом @ drawable / my_image xml, напрямую относятся к изображениям, которые хранятся в каталоге res / drawable в моем проекте.

Мне интересно, если это явно не хорошо, чтобы создать подкаталог в каталоге Drawable.

Например, если у меня была следующая структура каталогов:

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

Могу ли я сослаться на изображение бутерброда с салатом из тунца как @ drawable / sandwiches / tunaOnRye

Или я должен сохранить иерархию в каталоге drawable.


16
Обратите внимание, что заглавные буквы не разрешены в каталоге res.
Тайлер

1
Вы можете сделать это только с Gradle: stackoverflow.com/a/19859379
Яир Кукелька

2
Возможно ли иметь каталоги SIBLING для рисования с возможностью рисования ? Итак, res / tanks / drawble- [hdpi .. и т.д.] и так далее?
Толстяк

Ответы:


546

Нет, механизм ресурсов не поддерживает подпапки в каталоге drawable, так что да - вам нужно сохранить эту иерархию плоской.

Макет каталога, который вы показали, не приведет ни к одному из доступных изображений.

Из моих собственных экспериментов кажется, что наличие подпапки с любыми элементами в этой res/drawableпапке приведет к сбою компилятора ресурсов, что не позволит R.javaправильно сгенерировать файл.


136
Начиная с Android 2.2, это не вызывает ошибку компилятора, но любые подкаталоги игнорируются при создании класса R. Это действительно отстой и затрудняет управление крупными проектами. = /
Ник Рейман

70
Полностью согласен. Им нужно найти лучшее решение, поддерживающее подпапки. Это не может быть так сложно.
ЗНК

13
Надеюсь, это скоро будет решено, у меня есть более 100 активов, и даже тогда я закодировал некоторые из них. Всего ночная кобыла пытается управлять каким-то незначительно сложным проектом.
Эмиль

14
Это соответствующая проблема в системе отслеживания проблем Android: code.google.com/p/android/issues/detail?id=2018
espinchi

44
проклинаю тебя андроид
Whitneyland

149

Обходной путь, который я использую (и, похоже, предпочитает сам Android), состоит в том, чтобы по существу заменить знак подчеркивания косой чертой, чтобы ваша структура выглядела примерно так:

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

Подход требует от вас тщательности в наименовании и не делает так, чтобы самим было легко разбираться в файлах (если вы решили, что напитки и бутерброды действительно должны быть " food", вам придется сделать массовое переименование, а не просто перемещение их в каталог); но сложность вашей внутренней логики не пострадало слишком сильно по сравнению со структурой папок эквивалента.

Эта ситуация действительно отстой. Android представляет собой смешанный пакет замечательных и ужасных дизайнерских решений. Мы можем только надеяться, что последняя часть будет отсеяна со всей поспешностью :)


31
Просто обратите внимание, что заглавные буквы не допускаются в папке для рисования. Я получаю сообщение об ошибке: «Неверное имя файла: должно содержать только [a-z0-9_.]»
Джейсон Аксельсон

5
+1 за «смешанную сумку замечательных и ужасных дизайнерских решений»
Брент Фауст

1
Вряд ли это обходной путь: скорее «что нужно делать, чтобы не сходить с ума». Смешно быть ограниченным одним каталогом.
RichieHH

35

На самом деле, на Android Studio это возможно. Вы можете иметь вложенные ресурсы, как показано здесь :

введите описание изображения здесь

Существует также плагин для группы ресурсов здесь .


Привет, разработчик @android! Я попытался добавить это в файл build.gradle: sourceSets {main {res {srcDir 'src / main / res / drawable / ic-toggle'}}}, но у меня есть "Uri не зарегистрирован" для xmlns : android = " schemas.android.com/apk/res/android . В чем может быть дело?
AlexKost

@AlexKost Я действительно попробовал это только один раз. Я недостаточно опытен, чтобы помочь. Сожалею.
Android-разработчик

@RahulMandaliya Даже если это возможно, я предлагаю не использовать его.
Android-разработчик

@androiddeveloper Почему нет?
Джош Хансен

1
@JoshHansen Это грязно.
Android-разработчик

34

Да - это отстой :) Однако вы можете использовать папку активов и иметь подкаталоги там и загружать изображения таким образом.


6
проблема не только в папке drawable, но и в папке макета :( Папка моего макета содержит более 100 XML-файлов, и мне трудно открыть правильный макет XML в этом.
anticafe

За исключением других возражений, ресурсы могут быть легко локализованы, но в AFAIK нет встроенного механизма для активов.
Фран Марзоа

@anticafe использует «Перейти к ресурсу» в вашей среде IDE (Eclipse: CTRL + SHIFT + R, IDEA / Android Studio: CTRL + SHIFT + N)
TWiStErRob

23

Использовать папку ресурсов.

образец кода:

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

image = BitmapFactory.decodeStream(is);

5
Единственная проблема этого метода заключается в том, что с использованием растровых изображений гораздо больше домашних заданий. Система ресурсов Android намного лучше справляется с управлением памятью. Зачем вам перестраивать систему управления памятью, когда Android уже это делает? Особенно, если у него более 100 изображений, это много загружает и выпускает растровые изображения.
Преподобный Тайлер

18
Это реальная проблема, если вы планируете локализовать свое приложение, даже если у вас есть разные ресурсы для разных плотностей экрана, поэтому это не решение, а обходной путь, действительный только для некоторых случаев.
Фран Марзоа

1
Мне нужно дать @Fran's комментарий как минимум тысячу голосов :)
HGPB

22

Я написал плагин eclipse, который позволяет создавать виртуальную подпапку, разделяя имя файла двумя подчеркиваниями __. Проект находится на ранней стадии, но не волнуйтесь, он не сломает вашу IDE

Более подробную информацию можно найти здесь, не стесняйтесь раскошелиться и отправлять запросы на извлечение:

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

введите описание изображения здесь


2
Ницца! Есть ли шанс перенести это на Android Studio?
BVB

1
В настоящее время я даже не использую Android Studio, так что, думаю, нам придется подождать, пока некоторые опытные разработчики перенесут его.
Кирилл Кулаков

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

1
Ваш скрипт не будет работать, если в папках есть подпапки. Я думаю, вам нужно заменить все '/' на '_' в $ {dir}.
Seunghoon

9

В Android Studio с Gradle вы можете иметь несколько директоров источников, которые позволят вам разделить ресурсы. Например:

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

Однако имена не должны совпадать, что означает, что вам все равно нужно иметь такие имена, как sandwiches_tunaOnRye, но у вас будет возможность иметь отдельный раздел для всех ваших сэндвичей.

Это позволяет хранить ваши ресурсы в разных структурах (полезно для автоматически сгенерированного контента, такого как actionbargenerator)


4

Один из способов частично обойти проблему - использовать суффикс уровня API. Я использую res / layout-v1, res / layout-v2 и т. Д. Для хранения нескольких подпроектов в одном apk. Этот механизм может использоваться для всех типов ресурсов.

Очевидно, это можно использовать, только если вы нацеливаетесь на уровни API выше res / layout-v? ты используешь.

Также следите за ошибкой в ​​Android 1.5 и 1.6. См. Документацию Andoroid о суффиксе уровня API .


Кто бы ни понизил этот ответ: Вы можете объяснить почему? Этот механизм, хотя и не красивый, хорошо работает для меня.
OferR

4

С появлением библиотечной системы создание библиотеки на большой набор ресурсов может стать решением.

Это по-прежнему проблематично, так как следует избегать использования одинаковых имен во всех ресурсах, но использование схемы префикса для библиотеки должно помочь в этом.

Это не так просто, как возможность создавать папки, но это помогает держать вещи в здравом уме ...


Да, я думаю это хорошо. Если я добавлю флаги стран в мои папки drawable-ldpi и т. Д., Они будут забиты. Я думаю, что создание проекта библиотеки для всех общих ресурсов поможет уменьшить беспорядок в проекте, над которым вы активно работаете. Удивлен, у вас есть только 1 голос.
Том

3

В этой ситуации есть обходной путь: вы можете создать resVector(например) папку на том же уровне, что и resпапка по умолчанию . Там вы можете добавить drawable-xxxтуда любые папки ресурсов:

resVector
-drawable
-layout
-color

После этого все, что вам нужно, это добавить

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

в ваш build.gradleфайл (внутри android { }).


К сожалению, они объединяются в панели проектов в Android Studio при использовании перспективы «Android» :(
AjahnCharles

@AjahnCharles - я предпочитаю вообще не использовать эту перспективу (во всяком случае - я всегда работаю в «режиме без отвлечения») ... Но вы правы - «Android» объединяет все.
Антон Деревянко

1

Это не идеальные методы. Вы должны реализовать тот же способ, который отображается здесь .

Вы также можете вызвать изображение в папке через код, который вы можете использовать

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

TextView tv = (TextView)findViewByID(R.id.textview);
tv.setBackground(shape);

1

Не моя, но я нашел эту ветку, когда искал эту проблему, если вы используете Android Studio и систему Gradle Build, это довольно просто, никаких плагинов не требуется, просто небольшое редактирование файла сборки

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


1

Gradle с Android Studio может сделать это таким образом ( ссылка ).

Это в пункте «Настройка структуры»

sourceSets {
 main {
    java {
        srcDir 'src/java'
    }
    resources {
        srcDir 'src/resources'
    }
 }
}

1

создать папку в главном. как: 'res_notification_btn'

и создать папку дерева в. как «Drawable» или «макет»

затем в «build.gradle» добавить это

sourceSets
            {
                main
                {
                    res
                    {
                        srcDirs = ['src/main/res_notification_btn', 'src/main/res']
                      or
                        srcDir 'src/main/res_notification_btn'
                    }
                }
            }

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?("/")
}

Все это делает автоматизировать обходной путь, предложенный Cheezmeister. Это работает для меня ... не хочешь объяснить отрицательный голос?
Блейк Миллер


0

assets / Вы можете использовать его для хранения необработанных файлов активов. Файлы, которые вы сохраняете здесь, скомпилированы в файл .apk как есть, и исходное имя файла сохраняется. Вы можете перемещаться по этому каталогу так же, как и в обычной файловой системе, используя URI, и читать файлы как поток байтов, используя AssetManager. Например, это хорошее место для текстур и игровых данных. http://developer.android.com/tools/projects/index.html


0

Подкаталоги недопустимы, ресурс должен содержать только [a-z0-9_.].

Нет у вас заглавных букв и нет косой черты.


-3
  1. Щелкните правой кнопкой мыши на Drawable
  2. Выберите New ---> Directory
  3. Введите имя каталога. Например: logo.png (по умолчанию в папке уже будет отображаться папка для рисования)
  4. Скопируйте и вставьте изображения прямо в папку для рисования. При вставке вы можете выбрать mdpi / xhdpi / xxhdpi и т. Д. Для каждого изображения из списка. Выберите соответствующую опцию и введите название изображения. Убедитесь, что имя совпадает с именем каталога, т.е. logo.png
  5. Сделайте то же самое для оставшихся изображений. Все они будут размещены в главной папке logo.png.
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.