La directory di disegno di Android può contenere sottodirectory?


497

Nella documentazione dell'SDK di Android, tutti gli esempi utilizzati con la sintassi xml @ drawable / my_image indirizzano direttamente le immagini archiviate nella directory res / drawable nel mio progetto.

Mi chiedo se non sia esplicitamente giusto creare una sottodirectory all'interno della directory di disegno.

Ad esempio, se avessi il seguente layout di directory:

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

Potrei fare riferimento all'immagine di un panino con insalata di tonno come @ drawable / sandwiches / tunaOnRye

O devo mantenere la gerarchia piatta nella directory di disegno.


16
Si noti che le lettere maiuscole non sono consentite nella directory res.
Tyler,

1
Si può fare solo con Gradle: stackoverflow.com/a/19859379
Yair Kukielka

2
È possibile avere directory SIBLING su drawable, con la funzionalità drawable? Quindi, res / tanks / drawble- [hdpi .. etc] e così via?
Fattie,

Risposte:


546

No, il meccanismo delle risorse non supporta le sottocartelle nella directory di disegno, quindi sì: è necessario mantenere piatta quella gerarchia.

Il layout della directory che hai mostrato non renderebbe disponibile nessuna delle immagini.

Dai miei esperimenti sembra che avere una sottocartella con tutti gli elementi in essa contenuti, all'interno della res/drawablecartella, provochi il malfunzionamento del compilatore di risorse, impedendo la R.javacorretta generazione del file.


136
A partire da Android 2.2, ciò non causa un errore del compilatore, ma eventuali sottodirectory vengono ignorate durante la generazione della classe R. Questo fa davvero schifo e rende difficile gestire progetti più grandi. = /
Nik Reiman il

70
Completamente d'accordo. Devono trovare una soluzione migliore che supporti le sottocartelle. Non può essere così difficile.
znq,

13
Spero che questo venga risolto presto, ho oltre 100 risorse e anche allora ne ho codificate alcune. Cavalla notturna totale che cerca di gestire qualsiasi progetto marginalmente complesso.
Emile,

14
Questo è il problema corrispondente nel tracker dei problemi di Android: code.google.com/p/android/issues/detail?id=2018
espinchi,

44
ti maledico androide
Whitneyland,

149

La soluzione alternativa che sto usando (e quello che Android stesso sembra favorire) è essenzialmente di sostituire un carattere di sottolineatura con una barra, quindi la tua struttura sarebbe simile a questa:

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

L'approccio richiede che tu sia meticoloso nella tua denominazione e non semplifica molto la confusione dei file stessi (se decidi che bevande e sandwich dovrebbero davvero essere tutti " food", dovresti fare una ridenominazione di massa piuttosto che semplicemente spostandoli nella directory); ma la complessità della tua logica di programmazione non soffre troppo male rispetto all'equivalente della struttura di cartelle.

Questa situazione fa davvero schifo. Android è un miscuglio di decisioni di design meravigliose e terribili. Possiamo solo sperare che quest'ultima parte venga eliminata con tutta la dovuta fretta :)


31
Solo una nota che le lettere maiuscole non sono consentite nella cartella disegnabile. Viene visualizzato l'errore: "Nome file non valido: deve contenere solo [a-z0-9_.]"
Jason Axelson,

5
+1 per "miscuglio di meravigliose e terribili decisioni di design"
Brent Faust,

1
Difficilmente una soluzione alternativa: piuttosto "cosa dovresti fare per non impazzire completamente". È ridicolo essere limitato a una directory.
RichieHH,

35

In realtà, su Android Studio è possibile. Puoi avere risorse nidificate come mostrato qui :

inserisci qui la descrizione dell'immagine

C'è anche un plugin per raggruppare le risorse qui .


Ciao sviluppatore @android! Ho provato ad aggiungere questo nel file build.gradle: sourceSets {main {res {srcDir 'src / main / res / drawable / ic-toggle'}}}, ma ho "Uri non registrato" per xmlns : android = " schemas.android.com/apk/res/android . Quale potrebbe essere il caso?
AlexKost

@AlexKost In realtà ci ho provato solo una volta. Non ne ho abbastanza esperienza per aiutare. Scusate.
sviluppatore Android il

@RahulMandaliya Anche se è possibile, suggerisco di non usarlo.
sviluppatore Android

@androiddeveloper Perché no?
Josh Hansen,

1
@JoshHansen È disordinato.
Sviluppatore Android

34

Sì, fa schifo :) Tuttavia puoi usare la cartella delle risorse e avere sottodirectory lì e caricare le immagini in quel modo.


6
il problema non è solo per la cartella disegnabile ma anche per la cartella layout :( La cartella del mio layout contiene più di 100 file XML, ed è difficile per me aprire il layout XML giusto in questo.
anticafe

Oltre ad altre obiezioni, le risorse possono essere facilmente localizzate ma AFAIK non esiste un meccanismo incorporato per le risorse.
Fran Marzoa,

@anticafe usa "Vai alla risorsa" nel tuo IDE (Eclipse: CTRL + MAIUSC + R, IDEA / Studio Android: CTRL + MAIUSC + N)
TWiStErRob,

23

Usa la cartella delle risorse.

codice di esempio:

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

image = BitmapFactory.decodeStream(is);

5
L'unico problema con questo metodo è che ci sono MOLTO più compiti a casa con l'utilizzo di bitmap. Il sistema di risorse di Android fa un lavoro molto migliore nella gestione della memoria. Perché ricostruire un sistema di gestione della memoria quando Android lo fa già? Espeicamente se ha più di 100 immagini, è un sacco di caricamento e rilascio di bitmap.
Rev Tyler,

18
Questo è un vero problema se hai intenzione di localizzare la tua applicazione, anche se disponi di risorse diverse per diverse densità dello schermo, quindi non è una soluzione, solo una soluzione valida solo per alcuni casi.
Fran Marzoa,

1
Devo dare il commento di @Fran almeno un migliaio di voti :)
HGPB

22

Ho scritto un plugin eclipse che consente di creare una sottocartella virtuale separando il nome del file con due caratteri di sottolineatura __. Il progetto è in fase iniziale, ma non preoccuparti, non si bloccherà il tuo IDE

maggiori dettagli possono essere trovati qui, non esitate a fork e inviare richieste pull:

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

inserisci qui la descrizione dell'immagine


2
Bello! Qualche possibilità di portarlo anche su Android Studio?
BVB

1
Al momento non sto nemmeno usando Android Studio, quindi suppongo che dovremo aspettare un po 'di esperienza per portarlo.
Kirill Kulakov,

9

Mi piace usare un semplice script per appiattire una struttura di directory organizzata fornita dai progettisti a qualcosa che può essere utilizzato per generare un file R.

Esegui con il percorso corrente in 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
Lo script non funzionerà se sono presenti sottocartelle nelle cartelle. Penso che tu debba sostituire tutto '/' con '_' in $ {dir}.
Seunghoon,

9

In Android Studio con Gradle puoi avere direttori di sorgenti multiple che ti permetteranno di separare le risorse. Per esempio:

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

Tuttavia, i nomi non devono scontrarsi, il che significa che dovrai comunque avere nomi come sandwiches_tunaOnRye ma sarai in grado di avere una sezione separata per tutti i tuoi sandwich.

Ciò ti consente di archiviare le tue risorse in diverse strutture (utile per contenuti generati automaticamente come actionbargenerator)


4

Un modo per aggirare parzialmente il problema è utilizzare il suffisso Livello API. Uso res / layout-v1, res / layout-v2 ecc per contenere più progetti secondari nello stesso apk. Questo meccanismo può essere utilizzato per tutti i tipi di risorse.

Ovviamente, questo può essere utilizzato solo se si sta targetizzando livelli API superiori a res / layout-v? tu stai usando.

Inoltre, fai attenzione al bug in Android 1.5 e 1.6. Consulta la documentazione di Andoroid sul suffisso del livello API .


A chiunque abbia declassato questa risposta: puoi spiegare perché? Questo meccanismo, sebbene non carino, funziona bene per me.
OferR,

4

Con l'avvento del sistema di biblioteche, la creazione di una biblioteca per un grande insieme di risorse potrebbe essere una soluzione.

È ancora problematico in quanto si deve evitare di usare gli stessi nomi all'interno di tutte le risorse, ma l'utilizzo di uno schema di prefisso per libreria dovrebbe essere di aiuto.

Non è semplice come essere in grado di creare cartelle ma aiuta a mantenere le cose sane ...


Sì, penso che sia buono. Se aggiungo bandiere di paesi alle mie cartelle drawable-ldpi ecc., Verranno sommerse. Penso che la creazione di un progetto di libreria per tutte le risorse generiche contribuirà a ridurre il disordine nel progetto su cui stai lavorando attivamente. Sorpreso hai solo 1 voto.
Tom,

3

Esiste una soluzione alternativa per questa situazione: è possibile creare una resVectorcartella (ad esempio) allo stesso livello della rescartella predefinita . Lì puoi aggiungere qualsiasi drawable-xxxcartella di risorse lì:

resVector
-drawable
-layout
-color

Dopo di che tutto ciò che serve è aggiungere

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

nel tuo build.gradlefile (all'interno android { }).


Purtroppo si uniscono nel pannello del progetto in Android Studio quando si utilizza la prospettiva "Android" :(
AjahnCharles

@AjahnCharles - Preferisco non usare affatto questa prospettiva (comunque - lavoro sempre in "modalità senza distrazioni") ... Ma hai ragione: "Android" unisce tutto.
Anton Derevyanko,

1

Questo non è un metodo perfetto. Devi implementare allo stesso modo che viene visualizzato qui .

Puoi anche chiamare l'immagine nella cartella tramite il codice che puoi usare

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

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


1

Gradle con Android Studio potrebbe farlo in questo modo ( link ).

È nel paragrafo "Configurazione della struttura"

sourceSets {
 main {
    java {
        srcDir 'src/java'
    }
    resources {
        srcDir 'src/resources'
    }
 }
}

1

crea una cartella in principale. come: 'res_notification_btn'

e crea una cartella ad albero in. come 'drawable' o 'layout'

quindi in 'build.gradle' aggiungi questo

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

Tutto ciò che fa è automatizzare la soluzione suggerita da Cheezmeister. Funziona per me ... ti interessa spiegare il downvote?
Blake Miller,


0

risorse / È possibile utilizzarlo per archiviare file di risorse non elaborate. I file salvati qui vengono compilati in un file .apk così com'è e il nome file originale viene conservato. È possibile navigare in questa directory allo stesso modo di un tipico file system utilizzando gli URI e leggere i file come un flusso di byte utilizzando AssetManager. Ad esempio, questa è una buona posizione per trame e dati di gioco. http://developer.android.com/tools/projects/index.html


0

Le sottodirectory non sono consentite, la risorsa deve contenere solo [a-z0-9_.].

No, hai lettere maiuscole e nessuna barra.


-3
  1. Fare clic con il tasto destro su Drawable
  2. Seleziona Nuovo ---> Directory
  3. Inserisci il nome della directory. Ad esempio: logo.png (la posizione mostrerà già la cartella estraibile per impostazione predefinita)
  4. Copia e incolla le immagini direttamente nella cartella di disegno. Mentre si incolla si ottiene un'opzione per scegliere mdpi / xhdpi / xxhdpi ecc. Per ciascuna delle immagini da un elenco. Seleziona l'opzione appropriata e inserisci il nome dell'immagine. Assicurati di mantenere lo stesso nome del nome della directory, ad esempio logo.png
  5. Fai lo stesso per le immagini rimanenti. Tutti verranno posizionati nella cartella principale logo.png.
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.