Может ли папка Android Layout содержать подпапки? - PullRequest
512 голосов
/ 08 февраля 2011

Прямо сейчас я храню каждый XML-файл макета в папке res/layout, поэтому можно легко и просто управлять небольшими проектами, но в случае крупных и тяжелых проектов должна быть иерархия. и подпапки, необходимые внутри папки макета.

например

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

Точно так же мы хотели бы иметь подпапки для большого приложения, так есть ли способ сделать это внутри проекта Android?

Я могу создавать вложенные папки layout-personal и layout_address внутри папки layout, но когда приходит время доступа к файлу макета xml с помощью R.layout ._______, в это время не появляется никаких всплывающих окон xml вверх в меню.

Ответы [ 18 ]

452 голосов
/ 15 марта 2014

Вы МОЖЕТЕ сделать это с Gradle. Я сделал демонстрационный проект , показывающий как.

Хитрость заключается в том, чтобы использовать способность gradle объединить несколько папок ресурсов и установить папку res, а также вложенные подпапки в блоке sourceSets.

Причуда заключается в том, что вы не можете объявить папку ресурса контейнера до того, как объявите папки дочерних ресурсов этой папки.

Ниже приведен блок sourceSets из файла build.gradle из демоверсии. Обратите внимание, что подпапки объявляются первыми.

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

nested resources picture

Кроме того, непосредственный родительский элемент ваших фактических файлов ресурсов (pngs, XML-макеты и т. Д.) Все еще должен соответствовать спецификации .

231 голосов
/ 08 февраля 2011

Ответ - нет.

Я хотел бы обратить ваше внимание на эту книгу Pro Android 2 , в которой говорится:

Также стоит отметитьнесколько ограничений относительно ресурсов.Во-первых, Android поддерживает только линейный список файлов в предопределенных папках под res.Например, не поддерживает вложенные папки в папке макета (или в других папках под res).

Во-вторых, есть некоторые сходства между папкой assets и необработанной папкой под res,Обе папки могут содержать необработанные файлы, но файлы в необработанном виде считаются ресурсами, а файлы в активах - нет.

Обратите внимание, что поскольку содержимое папки assets не считается ресурсами, выможет поместить произвольную иерархию папок и файлов в it.

75 голосов
/ 25 августа 2015

Я просто хотел добавить к фантастическому ответу eskis для людей, имеющих проблемы.(Примечание: это будет работать и выглядеть как отдельные каталоги в представлении проекта, к сожалению, не в представлении android).

Протестировано со следующим.BuildToolsVersion = 23.0.0 gradle 1.2.3 & 1.3.0

Так я начал работать с уже созданным проектом.

  1. Скопируйте все файлы XML изваш каталог макета и поместите их в каталог на рабочем столе или что-то для резервного копирования.
  2. Удалите весь каталог макета (Убедитесь, что вы сделали резервную копию всего, начиная с шага 1 !!!)щелкните по каталогу res и выберите новый> каталог.
  3. Назовите этот новый каталог "layout".(Это может быть все, что вы хотите, но это не будет каталог 'фрагмент' или каталог 'деятельность', который появится позже).
  4. Щелкните правой кнопкой мыши новый каталог "layout" и выберите новый> каталог.(Это будет имя типа файлов XML, которые у вас будут в нем, например, «фрагменты» и «действия»).
  5. Щелкните правой кнопкой мыши каталог «фрагмент» или «действия» (Примечание:это не обязательно должен быть «фрагмент» или «деятельность», это то, что я использую в качестве примера), еще раз выберите new> directory и назовите этот каталог «layout».(Примечание: это ДОЛЖНО называться «layout» !!! очень важно).
  6. Поместите нужные файлы XML в новый каталог «layout» из резервной копии, которую вы сделали на рабочем столе.
  7. Повторите шаги 5 - 7 для любого количества пользовательских каталогов, сколько пожелаете.
  8. После этого перейдите в файл 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'
                    ]
        }
    }
    
  9. Прибыль $$$$

А если серьезно ... вот как я заставил это работать.Дайте мне знать, если у кого-то возникнут вопросы ... Я могу попытаться помочь.

Изображения стоят больше, чем слова.

Directory Structure

52 голосов
/ 22 октября 2011

Не возможно, но папка макета отсортирована по имени. Итак, я добавляю имена файлов макета с именами моих пакетов. Например. для двух пакетов «покупка» и «игра»:

buying_bought_tracks.xml
buying_buy_tracks.xml
playing_edit_playlist.xml
playing_play_playlist.xml
playing_show_playlists.xml
19 голосов
/ 28 августа 2015

Я использую Android File Grouping плагин для Android Studio. На самом деле он не позволяет вам создавать подпапки, но он может отображать ваши файлы и ресурсы, поскольку они находятся в разных папках. И это именно то, что я хотел.

Вы можете установить плагин "Android File Grouping" с помощью

Windows:

Android Studio -> Файл -> Настройки -> Плагины.

Mac:

Android Studio -> вкладка Android Studio (вверху слева) -> Настройки -> Плагины -> Установить плагин JetBrains ..

Для Mac я смог протестировать его и не смог найти плагин. Поэтому я скачал плагин с здесь и использовал опцию Install plugin from disk из вышеуказанных настроек.

18 голосов
/ 04 февраля 2014

Теперь с Android Studio и Gradle вы можете иметь несколько папок ресурсов в вашем проекте.Позволяет упорядочивать не только файлы макета, но и любые виды ресурсов.

Это не совсем подпапка, но может разделять части вашего приложения.

Конфигурация выглядит следующим образом:

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

Проверьте документацию .

16 голосов
/ 05 июня 2012

Я думаю, что наиболее элегантное решение этой проблемы (учитывая, что подпапки не допускаются) состоит в добавлении имени файла к имени папки, в которую вы бы поместили его. Например, если у вас есть несколько макетов для вида деятельности, фрагмента или просто общего вида, называемых «местами», то вам просто нужно добавить к нему местн По крайней мере, это решает проблему их организации таким образом, чтобы их было легче найти в среде IDE. Это не самое крутое решение, но лучше, чем ничего.

15 голосов
/ 29 апреля 2016

Небольшие проблемы

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

Однако по мере роста проекта у вас будет многоподпапки:

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
}

Вставьте этот метод вне блока android {...} в вашем app/build.gradle.


Как использовать

Для структуры, подобнойэто:

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

Надеюсь, это поможет!

11 голосов
/ 04 ноября 2017

Теперь мы можем легко сделать с плагином JetBrains под названием " Группировка файлов Android "

проверить эту ссылку

Группировка файлов Android

enter image description here

5 голосов
/ 23 августа 2017

Я сделал так, чтобы создать отдельную папку 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).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...