Czy folder układ systemu Android może zawierać podfoldery?

W tej chwili przechowuję każdy plik układu xml w folderze res/layout, więc zarządzanie małymi projektami jest wykonalne i proste, ale w przypadku dużych i ciężkich projektów, powinna istnieć hierarchia i podfoldery potrzebne w folderze układu.

Dla np.

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

Podobnie, chcielibyśmy mieć podfoldery dla dużej aplikacji, więc czy jest jakiś sposób, aby to zrobić wewnątrz projektu android?

Jestem w stanie stworzyć layout-osobisty i podfoldery layout_address wewnątrz folderu layout, ale gdy nadejdzie czas, aby uzyskać dostęp do pliku układu XML za pomocą R. layout._______ , w tym czasie nie ma żadnego wyskakującego okienka xml w menu.
Author: Lavekush Agrawal, 2011-02-08

18 answers

Możesz to zrobić z gradle. Zrobiłem Projekt demo pokazujący jak.

Sztuczka polega na użyciu zdolności gradle do scalania wielu folderów zasobów i ustawiania folderu res oraz zagnieżdżonych podfolderów w bloku sourceSets.

Ciekawostką jest to, że nie Można zadeklarować folderu zasobu kontenera przed zadeklarowaniem folderów zasobów potomnych tego folderu.

Poniżej znajduje się blok sourceSets z kompilacji.plik gradle z demo. Zauważ, że podfoldery są deklarowane jako pierwsze.

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

zagnieżdżone zasoby obraz

Również bezpośredni rodzic Twoich rzeczywistych plików zasobów (pngs, układy xml itp..) musi nadal odpowiadać specyfikacji .

 419
Author: eski,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-11-22 11:51:30

Odpowiedź brzmi nie.

Chciałbym zwrócić waszą uwagę na tę książkę Pro Android 2, która stwierdza:

Warto również zwrócić uwagę na kilka ograniczenia dotyczące zasobów. Po pierwsze, Android obsługuje tylko liniowy Lista plików w predefiniowanym foldery pod res. na przykład, to nie obsługuje zagnieżdżonych folderów pod folder layout (lub inny foldery pod res).

Po drugie, są pewne podobieństwa między folder zasoby i surowy folder pod res. oba foldery mogą zawierają pliki raw, ale pliki w surowych są uważane za zasoby a pliki w zasobach nie są.

Zauważ, że ponieważ zawartość aktywa folder nie są brane pod uwagę zasoby, można umieścić dowolny hierarchia folderów i plików w obrębie to.

 227
Author: 100rabh,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-06-21 14:20:50

[1]}chciałem tylko dodać do eskis fantastyczną odpowiedź dla ludzi mających problemy. (Uwaga: będzie to działać tylko i wyglądać jak oddzielne katalogi wewnątrz widoku "Projekt", a nie Widok "android" niestety.)

Przetestowane z następujących. BuildToolsVersion = 23.0.0 gradle 1.2.3 & 1.3.0

Tak dostałem mój do pracy z już zbudowanym projektem.

  1. skopiuj wszystkie pliki XML z katalogu układu i umieść je w katalogu na pulpicie lub coś dla wsparcia.
  2. usuń cały katalog układu (upewnij się, że wykonałeś kopię zapasową wszystkiego od kroku 1!!!)
  3. Kliknij prawym przyciskiem myszy katalog res i wybierz nowy > katalog.
  4. Nazwij ten nowy katalog "layouts". (Może to być cokolwiek chcesz, ale nie będzie to katalog' fragment 'lub' activity', który pojawi się później).
  5. Kliknij prawym przyciskiem myszy nowy katalog "układy" i wybierz nowy > katalog. (Będzie to nazwa typu plików XML, które będą w nim, na przykład "fragmenty" i "działania").
  6. Kliknij prawym przyciskiem myszy katalog 'fragment' lub 'activities' (uwaga: nie musi to być ' fragment 'lub ' activities', tego właśnie używam jako przykładu) i wybierz ponownie new > directory i nazwij ten katalog "layout". (Uwaga: To musi być nazwane 'layout'!!! bardzo ważne).
  7. Umieść żądane pliki XML w nowym katalogu 'layout' z kopii zapasowej wykonanej na pulpicie.
  8. powtórz kroki 5 - 7 Dla jak największej liczby niestandardowych katalogi jak chcesz.
  9. Po zakończeniu, przejdź do swoich modułów gradle.zbuduj plik i utwórz definicję sourceSets w ten sposób...(Upewnij się, że' src/main/res/layouts ' & 'src/main/res' są zawsze dwoma dolnymi!!!! Jak pokazuję poniżej).

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

Ale poważnie.. tak to działa. Daj znać, jeśli ktoś ma jakieś pytania.. Mogę spróbować pomóc.

Zdjęcia są warte więcej niż słowa.

Struktura Katalogów

 71
Author: hitch.united,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-08-25 03:12:16

Nie jest możliwe, ale katalog układu jest sortowany według nazwy. Tak więc dodaję nazwy plików układu z nazwami moich pakietów. Np. dla dwóch pakietów "kupowanie" i "granie":

buying_bought_tracks.xml
buying_buy_tracks.xml
playing_edit_playlist.xml
playing_play_playlist.xml
playing_show_playlists.xml
 51
Author: delformo,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-10-21 23:19:48

Teraz z Android Studio i Gradle, można mieć wiele folderów zasobów w projekcie. Pozwala organizować nie tylko Pliki układów, ale wszelkiego rodzaju zasoby.

Nie jest to dokładnie podfolder, ale może oddzielić części aplikacji.

Konfiguracja wygląda następująco:

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

Sprawdź dokumentację .

 18
Author: Androiderson,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-02-04 13:46:02

Używam Android grupowanie Plików plugin dla Androida Studio.It tak naprawdę nie pozwala na tworzenie podfolderów, ale może wyświetlać pliki i zasoby w różnych folderach. I tego właśnie chciałem.

Możesz zainstalować wtyczkę "grupowanie plików Androida" przez

Windows:

Android Studio - > Plik - > Ustawienia - > Wtyczki.

Mac:

Android Studio - > Zakładka Android Studio (Lewy Górny Róg) - > Preferencje - > Plugins - > Install JetBrains Plugin..

Dla komputerów Mac, byłem w stanie przetestować go i nie był w stanie wyszukać wtyczki. Więc pobrałem wtyczkę z tutaj i użyłem opcji Install plugin from disk z powyższego ustawienia.

 18
Author: Sharpe,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-10-13 14:58:54

Myślę, że najbardziej eleganckim rozwiązaniem tego problemu (biorąc pod uwagę, że podfoldery nie są dozwolone) jest dodanie nazwy pliku z nazwą folderu, w którym umieściłbyś go w środku. Na przykład, jeśli masz kilka układów dla aktywności, fragmentu lub po prostu widoku ogólnego o nazwie "miejsca", powinieneś poprzedzić je nazwą places_my_layout_name. Przynajmniej to rozwiązuje problem organizowania ich w sposób, który jest łatwiejszy do znalezienia w IDE. To nie jest najwspanialsze rozwiązanie, ale lepsze to niż nic.

 16
Author: botbot,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-06-05 02:41:37

Mały Problem

Jestem w stanie uzyskać podfoldery, podążając za najlepszą odpowiedzią na to pytanie.

Jednak, gdy projekt się rozrasta, będziesz miał wiele podfolderów:

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

Nie jest to wielki problem, ale:

  • to nie jest ładne, ponieważ lista staje się bardzo długa.
  • musisz zmienić swój app/build.gradle za każdym razem, gdy dodajesz nowy folder.

Poprawa

Więc napisałem prostą metodę Groovy, aby pobrać wszystkie zagnieżdżone foldery:

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
}

Wklej tę metodę poza blokiem android {...} w twoim app/build.gradle.


Jak używać

Dla takiej struktury:

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

Użyj go tak:

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

Jeśli masz taką strukturę:

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

Użyjesz go tak:

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

Wyjaśnienie

getLayoutList() przyjmuje a relative path jako argument. {[13] } jest w stosunku do korzenia projektu. Więc kiedy wejdziemy "app/src/main/res/layouts/", zwróci wszystkie podfoldery" nazwa tablicy, która będzie dokładnie taka sama jak:

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

Oto skrypt z komentarzami do zrozumienia:

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
}

Mam nadzieję, że to pomoże!

 11
Author: I'm a frog dragon,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 11:55:02

Teraz możemy łatwo zrobić z wtyczką JetBrains o nazwie "grupowanie plików Androida "

Sprawdź ten link

Grupowanie Plików Androida

Tutaj wpisz opis obrazka

 8
Author: Bharath Kumar Bachina,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-11-04 11:48:56

Sposobem, w jaki to zrobiłem, było utworzenie osobnego folderu res na tym samym poziomie, co rzeczywisty folder res w Twoim projekcie, a następnie użycie go w kompilacji aplikacji.gradle

android {
    //other stuff

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

przykładowa struktura folderów

Wtedy każdy podfolder nowego folderu res może być czymś związanym z każdym konkretnym ekranem lub czymś w Twojej aplikacji, a każdy folder będzie miał swój własny layout / drawable / values etc utrzymanie rzeczy zorganizowane i nie trzeba aktualizować pliku gradle ręcznie jak niektóre z tych innych odpowiedzi wymagają (po prostu zsynchronizuj swój gradle za każdym razem, gdy dodajesz nowy folder zasobów, aby wiedział o tym, i upewnij się, że dodałeś odpowiednie podfoldery przed dodaniem plików xml).

 5
Author: Fonix,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-08-16 12:27:05

Sprawdź skrypt Bash Flatten Folder który konwertuje hierarchię folderów do jednego folderu

 4
Author: Sneg,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-05-14 08:36:12

Jeśli tworzysz pliki na Linuksie lub komputerze mac, obejściem byłoby utworzenie podfolderów zawierających dowiązania symboliczne do plików układów. Wystarczy użyć komendy ln z -S

Ln-s PATH_TO_YOUR_FILE

Problem polega na tym, że twój folder układu nadal zawiera wszystkie .pliki xml. Ale możesz je wybrać za pomocą podfolderów. To najbliższa rzecz, do tego, co chciałbyś mieć.

Właśnie przeczytałem, że to może zadziałać z Windows, również jeśli używasz Vista lub nowszy. Jest to mklink polecenie. Po prostu wygoogluj go, nigdy go nie używałem.

Kolejny problem polega na tym, że jeśli masz otwarty plik i spróbuj go otworzyć ponownie, wtyczka rzuca wyjątek wskaźnika NULL. Ale nie rozłącza się.

 3
Author: Darokthar,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-02-08 07:47:52

Podczas gdy wszystkie propozycje dla wielu zestawów zasobów mogą działać, problem polega na tym, że obecna Logika dla wtyczki Android Studio Gradle nie zaktualizuje plików zasobów po ich zmianie Dla zagnieżdżonych zestawów zasobów. Obecna implementacja próbuje sprawdzić katalogi zasobów za pomocą funkcji startsWith(), więc struktura katalogów, która jest zagnieżdżona (np. src/main/res/layouts/layouts i src/main/res/layouts_category2) wybierze src/main/res/layouts/layouts konsekwentnie i nigdy nie Aktualizuj zmian. Efektem końcowym jest to, że za każdym razem musisz przebudować/wyczyścić projekt.

Złożyłem patch na https://android-review.googlesource.com/#/c/157971 / aby pomóc rozwiązać sprawy.

 3
Author: rogerhu,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-07-02 14:24:13

Najlepsza odpowiedź @eski jest dobra, ale kod nie jest elegancki w użyciu, więc napisałem groovy skrypt w gradle do ogólnego użytku. Jest stosowany do wszystkich typów kompilacji i smaku produktu i nie tylko może być używany do układu, można również dodać podfolder dla każdego innego typu zasobów, takiego jak drawable. Oto kod (umieść go w android bloku pliku gradle na poziomie projektu):

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

Jak to zrobić w praktyce?

Na przykład chcę utworzyć podfolder o nazwie activity dla layout, Dodać łańcuch dowolna nazwa zmiennej resDirs, np. layouts, wtedy plik XML układu należy umieścić w res\layouts\activity\layout\xxx.xml.

Jeśli chcę utworzyć podfolder o nazwie selectors dla drawable, dodać łańcuch o dowolnej nazwie w zmiennej resDirs, np. drawables, wtedy należy umieścić w res\drawables\selectors\drawable\xxx.xml drawable XML file.

Nazwa folderu, taka jak layouts i drawables jest zdefiniowana w zmiennej resDirs, może to być dowolny ciąg znaków. Wszystkie utworzone przez Ciebie podfoldery, takie jak activity lub selectors, są traktowane jako folder res. Więc w folderze selectors musimy Utwórz dodatkowo folder drawable i umieść pliki xml w folderze drawable, po czym gradle może rozpoznać pliki xml jako drawable normalnie.

 3
Author: AvatarQing,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-08-18 02:48:43
  • Krok 1: Kliknij prawym przyciskiem myszy układ-pokaż w Eksploratorze
  • Krok 2: Otwórz folder layout i utwórz bezpośrednio podfoldery: layout_1, layout_2 ...
  • Krok 3: Otwórz layout_1 Utwórz układ folderu (Uwaga: obowiązkowa nazwa to układ), otwórz folder layout_2 Utwórz podkatalog układu (Uwaga: obowiązkowa nazwa to układ)...
  • Krok 4: skopiuj pliki xml do podkatalogów layout_1 i layout_2
  • Krok 5: Uruchom kod w buid.grade (moduł app) I hit sync teraz:

sourceSets {
    main {
        res.srcDirs =
            [
                'src / main / res / layout / layout_1'
                'src / main / res / layout / layout_2',
                'src / main / res'
            ]
    }
}
  • Krok 6: podsumowanie: wszystkie powyższe kroki pomogą tylko w grupowaniu folderów i wyświetlaniu w trybie "projekt", podczas gdy tryb "android" będzie wyświetlany normalnie.
  • więc rysuję, że może nazewnictwo prefiksów jest tak samo skuteczne, jak klastrowanie folderów.
 1
Author: O Thạnh Ldt,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-01-04 02:53:42

Jeśli używasz metody w zatwierdzonej odpowiedzi i chcesz ją nieco poprawić, zmień ustawienie gradle w następujący sposób:

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

Więc jeśli dodasz więcej folderów i układów, nie musisz tu wracać i dołączać długiej listy folderów źródłowych, pozwól gradle uzyskać wszystkie foldery za Ciebie.

 1
Author: Drusantia,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-06-22 08:41:57

Krótka odpowiedź brzmi: nie. Ale na pewno możesz mieć wiele res folderów. To, jak sądzę, jest tak blisko, jak możesz dostać się do posiadania podfolderów dla folderu layout. Oto jak to zrobisz.

 0
Author: sravan953,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-05-25 11:54:13

Najlepsze odpowiedzi mają kilka wad: musisz dodać nowe ścieżki układu, ponieważ umieszcza nowe zasoby w folderze res\layouts zamiast res\values.

Łącząc kilka odpowiedzi napisałem podobne:

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

Zrobiłem foldery z tym artykułem: http://alexzh.com/tutorials/how-to-store-layouts-in-different-folders-in-android-project/. aby utworzyć podfoldery należy skorzystać z menu: New > Folder > Res Folder.

UPDATE

Po kilku tygodniach okazało się, że zmiany w zasobach nie są zauważane przez Android Studio . Więc pojawiają się jakieś dziwne robaki. Na przykład, układy nadal pokazują stare rozmiary, marginesy. Czasami AS Nie znajduje nowych plików XML (szczególnie podczas wykonywania). Czasami miesza view id s (odniesienia do innego pliku XML). Często wymagane jest naciśnięcie Build > Clean Project lub Build > Rebuild Project. Read odbudować wymagane po zmianie plików układów XML w Android Studio .

 0
Author: CoolMind,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-08-28 13:57:26