Kann das Android-Zeichenverzeichnis Unterverzeichnisse enthalten?

496

In der Android SDK-Dokumentation adressieren alle Beispiele, die mit der XML-Syntax @ drawable / my_image verwendet werden, direkt Bilder, die im Verzeichnis res / drawable in meinem Projekt gespeichert sind.

Ich frage mich, ob es ausdrücklich nicht in Ordnung ist, ein Unterverzeichnis innerhalb des Zeichenverzeichnisses zu erstellen.

Zum Beispiel, wenn ich das folgende Verzeichnislayout hätte:

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

Könnte ich das Bild eines Thunfischsalat-Sandwichs als @ drawable / sandwiches / tunaOnRye bezeichnen?

Oder muss ich die Hierarchie im Zeichenverzeichnis flach halten?

Pfeffer Lebeck-Jobe
quelle
16
Bitte beachten Sie, dass Großbuchstaben im Verzeichnis res nicht zulässig sind.
Tyler
1
Sie können dies nur mit Gradle tun: stackoverflow.com/a/19859379
Yair Kukielka
2
Ist es möglich, SIBLING- Verzeichnisse mit der Funktion drawable zum Zeichnen zu haben ? Also, res / tank / drawble- [hdpi .. etc] und so weiter?
Fattie

Antworten:

545

Nein, der Ressourcenmechanismus unterstützt keine Unterordner im Zeichenverzeichnis. Ja, Sie müssen diese Hierarchie flach halten.

Das von Ihnen angezeigte Verzeichnislayout würde dazu führen, dass keines der Bilder verfügbar ist.

Aus meinen eigenen Experimenten geht hervor, dass ein Unterordner mit Elementen im res/drawableOrdner dazu führt, dass der Ressourcen-Compiler fehlschlägt und die R.javaDatei nicht korrekt generiert wird.

Reto Meier
quelle
135
Ab Android 2.2 verursacht dies keinen Compilerfehler, aber alle Unterverzeichnisse werden beim Generieren der R-Klasse ignoriert. Das ist wirklich scheiße und macht es schwierig, größere Projekte zu verwalten. = /
Nik Reiman
69
Stimme voll und ganz zu. Sie müssen eine bessere Lösung finden, die Unterordner unterstützt. Es kann nicht so schwer sein.
znq
13
Hoffentlich wird dies bald behoben, ich habe über 100 Assets und selbst dann habe ich einige davon codiert. Totaler Albtraum, der versucht, ein marginal komplexes Projekt zu verwalten.
Emile
14
Dies ist das entsprechende Problem im Android Issue Tracker: code.google.com/p/android/issues/detail?id=2018
espinchi
44
verfluche dich android
whitneyland
149

Die Problemumgehung, die ich verwende (und die Android selbst zu bevorzugen scheint), besteht darin, einen Schrägstrich durch einen Unterstrich zu ersetzen, sodass Ihre Struktur ungefähr so ​​aussehen würde:

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

Der Ansatz erfordert, dass Sie bei der Benennung akribisch vorgehen und es nicht viel einfacher machen, die Dateien selbst zu bearbeiten (wenn Sie entschieden haben, dass Getränke und Sandwiches wirklich alle " food" sein sollten, müssten Sie eine Massenumbenennung vornehmen , anstatt einfach Verschieben in das Verzeichnis); Die Komplexität Ihrer Programmierlogik leidet jedoch nicht allzu stark im Vergleich zur entsprechenden Ordnerstruktur.

Diese Situation ist in der Tat scheiße. Android ist eine Mischung aus wunderbaren und schrecklichen Designentscheidungen. Wir können nur hoffen, dass der letzte Teil mit aller Eile ausgesondert wird :)

Cheezmeister
quelle
31
Nur ein Hinweis, dass Großbuchstaben im Zeichenordner nicht zulässig sind. Ich erhalte die Fehlermeldung: "Ungültiger Dateiname: darf nur [a-z0-9_.] Enthalten"
Jason Axelson
5
+1 für "gemischte Tasche von wunderbaren und schrecklichen Designentscheidungen"
Brent Faust
1
Kaum eine Problemumgehung: eher "was Sie tun sollten, um nicht völlig verrückt zu werden". Es ist lächerlich, auf ein Verzeichnis beschränkt zu sein.
RichieHH
35

Eigentlich ist es unter Android Studio möglich. Sie können verschachtelte Ressourcen wie hier gezeigt haben :

Geben Sie hier die Bildbeschreibung ein

Es gibt auch ein Plugin Gruppe Ressourcen hier .

Android-Entwickler
quelle
Hallo, @ Android Entwickler! Ich habe versucht, dies in die Datei build.gradle einzufügen: sourceSets {main {res {srcDir 'src / main / res / drawable / ic-toggle'}}}, aber ich habe "Uri ist nicht registriert" für xmlns : android = " schemas.android.com/apk/res/android . Was könnte der Fall sein?
AlexKost
@AlexKost Ich habe das eigentlich nur einmal versucht. Ich habe nicht genug Erfahrung damit, um zu helfen. Es tut uns leid.
Android-Entwickler
@ RahulMandaliya Obwohl es möglich ist, schlage ich vor, es nicht zu verwenden.
Android-Entwickler
@androiddeveloper Warum nicht?
Josh Hansen
1
@ JoshHansen Es ist chaotisch.
Android-Entwickler
34

Ja - es ist scheiße :) Sie können jedoch den Assets-Ordner verwenden und dort Unterverzeichnisse haben und Bilder auf diese Weise laden.

dijipiji
quelle
6
Das Problem betrifft nicht nur den zeichnbaren Ordner, sondern auch den Layoutordner :( Der Ordner meines Layouts enthält mehr als 100 XML-Dateien, und es fällt mir schwer, das richtige XML-Layout in diesem Ordner zu öffnen.
anticafe
Abgesehen von anderen Einwänden können Ressourcen leicht lokalisiert werden, aber AFAIK gibt es keinen eingebauten Mechanismus für Vermögenswerte.
Fran Marzoa
@anticafe benutze "Gehe zu Ressource" in deiner IDE (Eclipse: STRG + UMSCHALT + R, IDEE / Android Studio: STRG + UMSCHALT + N)
TWiStErRob
23

Verwenden Sie den Assets-Ordner.

Beispielcode:

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

image = BitmapFactory.decodeStream(is);
Milkia
quelle
5
Das einzige Problem bei dieser Methode ist, dass mit der Verwendung von Bitmaps viel mehr Hausaufgaben verbunden sind. Das Ressourcensystem von Android erledigt die Speicherverwaltung viel besser. Warum sollten Sie ein Speicherverwaltungssystem neu erstellen, wenn Android dies bereits tut? Insbesondere wenn er mehr als 100 Bilder hat, ist das viel Laden und Freigeben von Bitmaps.
Rev. Tyler
18
Dies ist ein echtes Problem, da Sie planen, Ihre Anwendung zu lokalisieren, auch wenn Sie über unterschiedliche Ressourcen für unterschiedliche Bildschirmdichten verfügen. Dies ist also keine Lösung, sondern nur eine Problemumgehung, die nur für einige Fälle gültig ist.
Fran Marzoa
1
Ich muss @Frans Kommentar mindestens tausend positive Stimmen geben :)
HGPB
22

Ich habe ein Eclipse-Plugin geschrieben, mit dem Sie einen virtuellen Unterordner erstellen können, indem Sie den Dateinamen durch zwei Unterstriche trennen __. Das Projekt befindet sich in einem frühen Stadium, aber keine Sorge, es wird Ihre IDE nicht zum Absturz bringen

Weitere Details finden Sie hier. Sie können gerne Pull-Anfragen senden:

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

Geben Sie hier die Bildbeschreibung ein

Kirill Kulakov
quelle
2
Nett! Gibt es eine Chance, dies auch auf Android Studio zu portieren?
BVB
1
Ich benutze derzeit nicht einmal Android Studio, also müssen wir wohl auf einige erfahrene warten, um es zu portieren.
Kirill Kulakov
9

Ich verwende gerne ein einfaches Skript, um eine von Designern bereitgestellte organisierte Verzeichnisstruktur auf etwas zu reduzieren, mit dem eine R-Datei generiert werden kann.

Mit aktuellem Pfad in drawable-hdpi ausführen:

#! /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
quelle
1
Ihr Skript funktioniert nicht, wenn sich Unterordner unter Ordnern befinden. Ich denke, Sie müssen alle '/' durch '_' in $ {dir} ersetzen.
Seunghoon
9

In Android Studio mit Gradle können Sie mehrere Quelldirektoren haben, mit denen Sie Ressourcen trennen können. Zum Beispiel:

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

Die Namen dürfen jedoch nicht kollidieren, was bedeutet, dass Sie weiterhin Namen wie Sandwiches_tunaOnRye benötigen, aber Sie können einen separaten Abschnitt für alle Ihre Sandwiches haben.

Auf diese Weise können Sie Ihre Ressourcen in verschiedenen Strukturen speichern (nützlich für automatisch generierte Inhalte wie den Aktionsleistengenerator).

Alec Holmes
quelle
4

Eine Möglichkeit, das Problem teilweise zu umgehen, besteht darin, das Suffix API Level zu verwenden. Ich benutze res / layout-v1, res / layout-v2 usw., um mehrere Unterprojekte in derselben apk zu halten. Dieser Mechanismus kann für alle Ressourcentypen verwendet werden.

Dies kann natürlich nur verwendet werden, wenn Sie API-Ebenen über dem res / layout-v? du benutzt.

Achten Sie auch auf den Fehler in Android 1.5 und 1.6. Weitere Informationen zum Suffix API Level finden Sie in der Andoroid-Dokumentation .

OferR
quelle
Wer auch immer diese Antwort herabgestuft hat: Können Sie erklären, warum? Dieser Mechanismus ist zwar nicht schön, funktioniert aber gut für mich.
OferR
4

Mit dem Aufkommen des Bibliothekssystems könnte das Erstellen einer Bibliothek pro großen Satz von Assets eine Lösung sein.

Es ist immer noch problematisch, da man vermeiden muss, in allen Assets dieselben Namen zu verwenden, aber die Verwendung eines Präfixschemas pro Bibliothek sollte dabei helfen.

Es ist nicht so einfach, Ordner zu erstellen, aber das hilft, die Dinge gesund zu halten ...

shi
quelle
Ja, ich finde das gut. Wenn ich meinen zeichner-ldpi usw.-Ordnern Länderflaggen hinzufüge, werden sie überflutet. Ich denke, dass das Erstellen eines Bibliotheksprojekts für alle allgemeinen Ressourcen dazu beiträgt, die Unordnung in dem Projekt zu verringern, an dem Sie aktiv arbeiten. Überrascht haben Sie nur 1 Gegenstimme.
Tom
3

Für diese Situation gibt es eine Problemumgehung: Sie können einen resVector(beispielsweise) Ordner auf derselben Ebene wie den Standardordner erstellen res. Dort können Sie beliebige drawable-xxxRessourcenordner hinzufügen :

resVector
-drawable
-layout
-color

Danach müssen Sie nur noch hinzufügen

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

in Ihre build.gradleDatei (innen android { }).

Anton Derevyanko
quelle
Leider werden sie im Projektfenster in Android Studio zusammengeführt, wenn die "Android" -Perspektive verwendet wird :(
AjahnCharles
@AjahnCharles - Ich bevorzuge es, diese Perspektive überhaupt nicht zu verwenden (sowieso - ich arbeite immer im ablenkungsfreien Modus) ... Aber Sie haben Recht - "Android" führt alles zusammen.
Anton Derevyanko
1

Dies ist keine perfekte Methode. Sie müssen dieselbe Art und Weise implementieren , die Anzeige ist hier .

Sie können das Bild unter dem Ordner auch über den Code aufrufen, den Sie verwenden können

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

TextView tv = (TextView)findViewByID(R.id.textview);
tv.setBackground(shape);
user3177928
quelle
1

Nicht meins, aber ich habe diesen Thread gefunden, als ich nach diesem Problem gesucht habe. Wenn Sie Android Studio und Gradle Build verwenden, ist es ziemlich einfach, keine Plugins erforderlich, nur ein wenig Bearbeitung der Build-Datei

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

Captnwalker1
quelle
1

Gradle mit Android Studio könnte es so machen ( Link ).

Es steht im Abschnitt "Konfigurieren der Struktur"

sourceSets {
 main {
    java {
        srcDir 'src/java'
    }
    resources {
        srcDir 'src/resources'
    }
 }
}
user3290180
quelle
1

Erstellen Sie einen Ordner in main. wie: 'res_notification_btn'

und erstellen Sie einen Baumordner in. wie 'zeichnbar' oder 'Layout'

Fügen Sie dies dann in 'build.gradle' hinzu

sourceSets
            {
                main
                {
                    res
                    {
                        srcDirs = ['src/main/res_notification_btn', 'src/main/res']
                      or
                        srcDir 'src/main/res_notification_btn'
                    }
                }
            }
Ali Bagheri
quelle
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
quelle
Dies automatisiert lediglich die von Cheezmeister vorgeschlagene Problemumgehung. Es funktioniert für mich ... möchten Sie die Ablehnung erklären?
Blake Miller
0

Assets / Sie können damit Roh-Asset-Dateien speichern. Dateien, die Sie hier speichern, werden unverändert in eine APK-Datei kompiliert, und der ursprüngliche Dateiname bleibt erhalten. Sie können in diesem Verzeichnis wie in einem typischen Dateisystem mithilfe von URIs navigieren und Dateien mit dem AssetManager als Bytestrom lesen. Dies ist beispielsweise ein guter Ort für Texturen und Spieldaten. http://developer.android.com/tools/projects/index.html

Alex M.
quelle
0

Unterverzeichnisse sind nicht zulässig, die Ressource darf nur [a-z0-9_.] Enthalten.

Nein, Sie haben Großbuchstaben und keine Schrägstriche.

Ferhat Aslan
quelle
-3
  1. Klicken Sie mit der rechten Maustaste auf Drawable
  2. Wählen Sie Neu ---> Verzeichnis
  3. Geben Sie den Verzeichnisnamen ein. Beispiel: logo.png (der Speicherort zeigt standardmäßig bereits den Zeichenordner an)
  4. Kopieren Sie die Bilder und fügen Sie sie direkt in den Zeichenordner ein. Beim Einfügen haben Sie die Möglichkeit, für jedes Bild aus einer Liste mdpi / xhdpi / xxhdpi usw. auszuwählen. Wählen Sie die entsprechende Option und geben Sie den Namen des Bildes ein. Stellen Sie sicher, dass Sie den gleichen Namen wie der Verzeichnisname verwenden, z. B. logo.png
  5. Machen Sie dasselbe für die restlichen Bilder. Alle werden unter dem Hauptordner logo.png abgelegt.
Afreen Hasheem Siraj
quelle