У меня есть приложение, и все макеты внутри папки res/layout становятся довольно крупными и сложными в управлении. Я хотел бы иметь папки для всех макетов. Я прочитал, что внутри папки макета не может быть подкаталогов, но может быть в папке с ресурсами. Поэтому мой вопрос: как мне получить доступ к файлу и установить его как мое представление из файла в каталоге ресурсов? Что-то вроде следующего
int assetId = getAssets().open("main.xml");
setContentView(assetId)
Будет ли приведенный выше код работать? Как установить этот файл xml для моего представления? Спасибо.
Короткий ответ: это невозможно сделать таким образом. Основные причины:
res/layout
все файлы .xml
предварительно скомпилированы, поэтому Android может использовать их в качестве ресурсов. В папке assets
все файлы остаются неповрежденными, поэтому приложение может читать их как обычные файлы. (В вашем примере кода вы получите InputStream
, а не идентификатор ресурса).res/layout
, в поисках наилучшего соответствия текущему разрешению экрана, ориентации, языку и т.д.Вы можете добиться этого, используя пользовательский script и выполнив его до выполнения сборки. Android, похоже, игнорирует что-либо в подкаталогах макета, поэтому вы можете безопасно разместить в них свои файлы. Следующий ruby script (написанный для Linux, но легко конвертируемый в другие платформы) удалит все, что не является каталогом в res/layout/, и скопируйте каждый файл из поддиретов в res/layout/:
#!/usr/bin/ruby
require "fileutils"
def collect_files(directory)
FileUtils.cd(directory)
FileUtils.rm(Dir.entries(directory).reject{|x| File.directory?(x)}) #Remove all layout files in base dir
files_to_copy=Dir.glob("**/*").reject{|x| File.directory?(x)}
files_to_copy.each{|x| print "Copying #{x} to #{directory}\n"}
FileUtils.cp(files_to_copy, directory) #Copy all files in subdir into base dir
end
if ARGV[0]!=nil && File.directory?(ARGV[0])
xml_dir=ARGV[0]
layout_dir="#{xml_dir}/layout"
collect_files(layout_dir)
else
puts("Must specify a valid directory!")
end
код > Будьте предупреждены, что приведенный выше script не является надежным и фактически удалит любые файлы макета не в подкаталоге. Вы всегда можете удалить шаг удаления, если хотите, но затем любые файлы, которые вы удаляете из подкаталогов, останутся в основном каталоге для последующих сборок.
Если вы запускаете Eclipse, вы можете настроить внешний инструмент, который вы можете добавить к своим разработчикам позже. Просто откройте Run → External Tools → External Tools Configurations и создайте новый инструмент в разделе "Программы". Вот пример моих настроек:
Примечание. Рабочий каталог - это красная селедка и не будет использоваться. Вам нужно указать место, где вы выпадаете script, а не тот, который показан здесь
Теперь вы можете добавить инструмент к строителям для своего проекта. Выберите проект и откройте Project → Properties. Теперь выберите элемент "Строители" и нажмите "Импорт". Вы должны увидеть свой инструмент там, если вы его успешно определили. Он должен быть запущен до остальной части процесса сборки, поэтому не забудьте переместить его в начало списка. Вот как это должно выглядеть, когда вы закончите:
Теперь вы просто перемещаете файлы макета в подкаталоги (но следите за коллизиями имен, помните, что все файлы будут в том же каталоге для сборки!) и создайте ваш проект. Вы увидите, как они волшебным образом появятся в корне /res/layout/, когда вы это сделаете, и ваше приложение должно затем нормально работать.
Caveat Scriptor: если вы указываете несколько макетов или что-то еще, которое использует больше, чем просто каталог /res/layout/, вам нужно расширить этот script или добавить инструмент несколько раз для различные каталоги для обработки. Я лично не использую эту технику и поэтому не видел, где она падает, но провела тест с помощью базового приложения Android Hello Hello с несколькими макетами в некоторых подкаталогах.
Кроме того, мой script будет разбит, если используется с путями, содержащими пробелы!
Я не думаю, что это хорошая идея, и, вероятно, просто не работает. Что будет делать инфраструктура, если она считает, что нужна версия hdpi вашего макета, например?
Вы можете попытаться выполнить основную причину распространения вашего макета:
-portrait
и -landscape
?layoutinflator может помочь вам Смотри сюда Что делает LayoutInflater в Android?