Czy wyciągalny katalog Androida może zawierać podkatalogi?

496

W dokumentacji zestawu SDK systemu Android wszystkie przykłady użyte w składni xml @ drawable / my_image bezpośrednio odnoszą się do obrazów przechowywanych w katalogu res / drawable w moim projekcie.

Zastanawiam się, czy jawnie nie można tworzyć podkatalogów w katalogu, który można wyciągnąć.

Na przykład gdybym miał następujący układ katalogu:

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

Czy mogę odnieść się do obrazu kanapki z sałatką z tuńczyka jako @ drawable / sandwichwic / tunaOnRye

Czy też muszę utrzymywać płaską hierarchię w katalogu do rysowania.

Papryka Lebeck-Jobe
źródło
16
Uwaga: duże litery nie są dozwolone w katalogu res.
Tyler,
1
Możesz to zrobić tylko za pomocą Gradle: stackoverflow.com/a/19859379
Yair Kukielka
2
Czy to możliwe, aby mieć rodzeństwo katalogi do rozciągliwej, z rozciągliwej funkcjonalności? Więc res / czołgi / drawble- [hdpi .. itd.] I tak dalej?
Fattie

Odpowiedzi:

545

Nie, mechanizm zasobów nie obsługuje podfolderów w katalogu do rysowania, więc tak - musisz utrzymać tę hierarchię na płasko.

Układ katalogu, który pokazałeś, nie spowodowałby, że żaden obraz nie byłby dostępny.

Z moich własnych eksperymentów wydaje się, że posiadanie podfolderu z dowolnymi elementami w res/drawablefolderze spowoduje awarię kompilatora zasobów - uniemożliwiając R.javaprawidłowe wygenerowanie pliku.

Reto Meier
źródło
135
Począwszy od Androida 2.2, nie powoduje to błędu kompilatora, ale wszystkie podkatalogi są ignorowane podczas generowania klasy R. To naprawdę jest do bani i utrudnia zarządzanie większymi projektami. = /
Nik Reiman
69
Kompletnie się zgadzam. Muszą wymyślić lepsze rozwiązanie obsługujące podfoldery. To nie może być takie trudne.
znq
13
Mam nadzieję, że problem zostanie wkrótce rozwiązany, mam ponad 100 zasobów, a nawet niektóre z nich zakodowałem. Klacz nocna stara się zarządzać jakimkolwiek marginalnie złożonym projektem.
Emile,
14
Jest to odpowiedni Problem w Android śledzenia błędów: code.google.com/p/android/issues/detail?id=2018
espinchi
44
przeklinam cię android
whitneyland
149

Obejście, którego używam (i ten sam Android wydaje się faworyzować), polega zasadniczo na zastąpieniu podkreślenia znakiem ukośnika, tak aby twoja struktura wyglądała mniej więcej tak:

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

Podejście to wymaga staranności w nadawaniu nazw i nie ułatwia oszukiwania samych plików (jeśli zdecydujesz, że napoje i kanapki tak naprawdę powinny być „ food”, musisz dokonać masowej zmiany nazwy, a nie po prostu przenoszenie ich do katalogu); ale złożoność logiki programistycznej nie cierpi zbytnio w porównaniu do równoważnej struktury folderów.

Ta sytuacja jest do kitu. Android to mieszanka wspaniałych i okropnych decyzji projektowych. Możemy mieć tylko nadzieję, że ta ostatnia porcja zostanie wyeliminowana z należytym pośpiechem :)

Cheezmeister
źródło
31
Tylko uwaga, że ​​duże litery nie są dozwolone w folderze, który można wyciągać. Pojawia się błąd: „Nieprawidłowa nazwa pliku: musi zawierać tylko [a-z0-9_.]”
Jason Axelson
5
+1 za „mieszany worek cudownych i okropnych decyzji projektowych”
Brent Faust
1
Prawie obejście: raczej „co powinieneś zrobić, aby nie oszaleć”. Śmiesznie jest być ograniczonym do jednego katalogu.
RichieHH,
35

W rzeczywistości jest to możliwe w Android Studio. Możesz zagnieżdżać zasoby, jak pokazano tutaj :

wprowadź opis zdjęcia tutaj

Istnieje również wtyczka do grupowania zasobów tutaj .

programista Androida
źródło
Cześć, programista @android! Próbowałem dodać to do pliku build.gradle: sourceSets {main {res {srcDir 'src / main / res / drawable / ic-toggle'}}}, ale mam „Uri nie jest zarejestrowany” dla xmlns : android = " schemas.android.com/apk/res/android . Co może mieć miejsce?
AlexKost
@AlexKost Próbowałem tego tylko raz. Nie mam wystarczającego doświadczenia, aby pomóc. Przepraszam.
programista Androida
@RahulMandaliya Nawet jeśli jest to możliwe, sugeruję, aby go nie używać.
programista Androida
@androiddeveloper Dlaczego nie?
Josh Hansen
1
@JoshHansen Jest bałagan.
programista Androida
34

Tak - to jest do kitu :) Możesz jednak użyć folderu zasobów i mieć tam podkatalogi i w ten sposób ładować obrazy.

dijipiji
źródło
6
problem polega nie tylko na rozciągliwej folderu do folderu, ale również układ :( folderu swojego układu zawiera więcej niż 100 plików xml, a to trudne dla mnie, aby otworzyć odpowiednią układ xml w tej sprawie.
anticafe
Oprócz innych zastrzeżeń zasoby mogą być łatwo zlokalizowane, ale AFAIK nie ma wbudowanego mechanizmu 1010 dla zasobów.
Fran Marzoa,
@anticafe użyj „Idź do zasobu” w swoim IDE (Eclipse: CTRL + SHIFT + R, IDEA / Android Studio: CTRL + SHIFT + N)
TWiStErRob
23

Użyj folderu zasobów.

przykładowy kod:

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

image = BitmapFactory.decodeStream(is);
milkia
źródło
5
Jedynym problemem związanym z tą metodą jest to, że przy użyciu map bitowych jest O wiele więcej zadań domowych. System zasobów Androida znacznie lepiej zarządza pamięcią. Dlaczego miałbyś przebudowywać system zarządzania pamięcią, skoro Android już to robi? Zwłaszcza jeśli ma ponad 100 zdjęć, to dużo ładowania i wydawania map bitowych.
Rev Tyler,
18
To prawdziwy problem, jeśli planujesz zlokalizować swoją aplikację, także jeśli masz różne zasoby dla różnych gęstości ekranu, więc nie jest to rozwiązanie, tylko obejście ważne tylko w niektórych przypadkach.
Fran Marzoa,
1
Muszę dać komentarz @Fran co najmniej tysiąc głosów pozytywnych :)
HGPB
22

Napisałem wtyczkę Eclipse, która pozwala utworzyć wirtualny podfolder, oddzielając nazwę pliku dwoma podkreślnikami __. Projekt jest na wczesnym etapie, ale nie martw się, nie spowoduje to awarii Twojego IDE

więcej szczegółów można znaleźć tutaj, nie krępuj się rozwiązywać i wysyłać żądania ściągania:

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

wprowadź opis zdjęcia tutaj

Kirill Kulakov
źródło
2
Miły! Czy jest jakaś szansa na przeniesienie tego do Android Studio?
BVB
1
Obecnie nawet nie korzystam z Android Studio, więc myślę, że będziemy musieli poczekać, aż jakiś doświadczony go przeniesie.
Kirill Kulakov
9

Lubię używać prostego skryptu, aby spłaszczyć zorganizowaną strukturę katalogów dostarczoną przez projektantów do czegoś, co można wykorzystać do wygenerowania pliku R.

Uruchom z bieżącą ścieżką w 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
Rene
źródło
1
Twój skrypt nie będzie działał, jeśli pod folderami znajdują się podfoldery. Myślę, że musisz zamienić wszystkie „/” na „_” w $ {dir}.
Seunghoon,
9

W Android Studio ze stopniem możesz mieć wielu dyrektorów źródłowych, co pozwoli ci oddzielić zasoby. Na przykład:

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

Jednak nazwy nie mogą się kolidować, co oznacza, że ​​nadal będziesz musiał mieć nazwy takie jak sandwiches_tunaOnRye, ale będziesz mógł mieć oddzielną sekcję dla wszystkich swoich kanapek.

Umożliwia to przechowywanie zasobów w różnych strukturach (przydatne w przypadku treści generowanych automatycznie, takich jak Actionbargenerator)

Alec Holmes
źródło
4

Jednym ze sposobów częściowego obejścia problemu jest użycie sufiksu poziomu interfejsu API. Korzystam z res / layout-v1, res / layout-v2 itp., Aby przechowywać wiele podprojektów w tym samym pliku APK. Tego mechanizmu można używać do wszystkich typów zasobów.

Oczywiście można tego użyć tylko wtedy, gdy celujesz w poziomy API powyżej res / layout-v? ty używasz.

Uważaj również na błąd w Androidzie 1.5 i 1.6. Zobacz dokumentację Andoroid dotyczącą sufiksu poziomu API .

OferR
źródło
Do tego, kto obniżył tę odpowiedź: Czy możesz wyjaśnić, dlaczego? Ten mechanizm, choć nie ładny, działa dla mnie dobrze.
OferR
4

Wraz z pojawieniem się systemu bibliotecznego rozwiązaniem może być utworzenie biblioteki dla dużego zestawu zasobów.

Jest to nadal problematyczne, ponieważ należy unikać używania tych samych nazw we wszystkich zasobach, ale użycie schematu prefiksu dla biblioteki powinno w tym pomóc.

Nie jest to tak proste, jak tworzenie folderów, ale pomaga zachować rozsądek ...

Shi
źródło
Tak, myślę, że to dobrze. Jeśli dodam flagi państw do folderów drawable-ldpi itp., Zostaną one zalane. Myślę, że utworzenie projektu biblioteki dla wszystkich zasobów ogólnych pomoże zmniejszyć bałagan w projekcie, nad którym aktywnie pracujesz. Zaskoczony, masz tylko 1 głos pozytywny.
Tom
3

Istnieje obejście tego problemu: możesz utworzyć resVector(na przykład) folder na tym samym poziomie, co resfolder domyślny . Tam możesz dodać dowolne drawable-xxxfoldery zasobów:

resVector
-drawable
-layout
-color

Następnie wystarczy dodać

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

do twojego build.gradlepliku (wewnątrz android { }).

Anton Derevyanko
źródło
Niestety, łączą się one w panelu projektu w Android Studio podczas korzystania z perspektywy „Android” :(
AjahnCharles
@AjahnCharles - Wolę w ogóle nie korzystać z tej perspektywy (w każdym razie - zawsze pracuję w trybie „bez rozpraszania uwagi”) ... Ale masz rację - „Android” łączy wszystko.
Anton Derevyanko
1

To nie są doskonałe metody. Musisz zaimplementować ten sam sposób, który jest tutaj wyświetlany .

Możesz także wywołać obraz w folderze za pomocą kodu, którego możesz użyć

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

TextView tv = (TextView)findViewByID(R.id.textview);
tv.setBackground(shape);
użytkownik3177928
źródło
1

Nie mój, ale znalazłem ten wątek, szukając tego problemu, jeśli używasz systemu Android Studio i systemu Gradle Build, jest to dość łatwe, nie wymaga żadnych wtyczek, wystarczy niewielka edycja pliku kompilacji

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

Captnwalker 1
źródło
1

Gradle z Android Studio może to zrobić w ten sposób ( link ).

Znajduje się w akapicie „Konfigurowanie struktury”

sourceSets {
 main {
    java {
        srcDir 'src/java'
    }
    resources {
        srcDir 'src/resources'
    }
 }
}
użytkownik3290180
źródło
1

utwórz folder w głównym. jak: „res_notification_btn”

i utwórz folder drzewa w. jak „rysowalny” lub „układ”

następnie w „build.gradle” dodaj to

sourceSets
            {
                main
                {
                    res
                    {
                        srcDirs = ['src/main/res_notification_btn', 'src/main/res']
                      or
                        srcDir 'src/main/res_notification_btn'
                    }
                }
            }
Ali Bagheri
źródło
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?("/")
}
Blake Miller
źródło
Wszystko to automatyzuje obejście zaproponowane przez Cheezmeistera. To działa dla mnie ... chcesz wyjaśnić opinię?
Blake Miller
0

zasoby / Możesz go użyć do przechowywania plików surowych zasobów. Zapisane tutaj pliki są kompilowane w istniejącym pliku .apk, a oryginalna nazwa pliku zostaje zachowana. Możesz poruszać się po tym katalogu w taki sam sposób, jak w typowym systemie plików za pomocą URI i odczytywać pliki jako strumień bajtów za pomocą AssetManager. Na przykład jest to dobra lokalizacja dla tekstur i danych gry. http://developer.android.com/tools/projects/index.html

Alex M.
źródło
0

Podkatalogi nie są dozwolone, zasób musi zawierać tylko [a-z0-9_.].

Nie, masz wielkie litery i żadnych ukośników.

Ferhat Aslan
źródło
-3
  1. Kliknij prawym przyciskiem myszy na Drawable
  2. Wybierz Nowy ---> Katalog
  3. Wpisz nazwę katalogu. Np .: logo.png (lokalizacja będzie domyślnie wyświetlać folder z możliwością rysowania)
  4. Skopiuj i wklej obrazy bezpośrednio do folderu, który można wyciągać. Podczas wklejania masz opcję wyboru mdpi / xhdpi / xxhdpi itp. Dla każdego obrazu z listy. Wybierz odpowiednią opcję i wprowadź nazwę obrazu. Pamiętaj, aby zachować tę samą nazwę co nazwa katalogu, np. Logo.png
  5. Zrób to samo dla pozostałych zdjęć. Wszystkie zostaną umieszczone pod folderem głównym logo.png.
Afreen Hasheem Siraj
źródło