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.


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.


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 :)


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 .


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.


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);

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


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

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)


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 .


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


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 { }).


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);


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

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

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

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


0

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

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


-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.
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.