Bisakah direktori Android drawable berisi subdirektori?

497

Dalam dokumentasi Android SDK, semua contoh yang digunakan dengan sintaks @ drawable / my_image xml secara langsung menangani gambar yang disimpan dalam direktori res / drawable di proyek saya.

Saya bertanya-tanya apakah secara eksplisit tidak apa-apa membuat sub direktori di dalam direktori drawable.

Misalnya, jika saya memiliki tata letak direktori berikut:

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

Bisakah saya merujuk gambar sandwich salad tuna sebagai @ drawable / sandwiches / tunaOnRye

Atau apakah saya harus menjaga agar hierarki tetap datar di direktori yang dapat digambar.

Pepper Lebeck-Jobe
sumber
16
Harap dicatat bahwa huruf kapital tidak diperbolehkan dalam direktori res.
Tyler
1
Anda hanya dapat melakukan ini dengan Gradle: stackoverflow.com/a/19859379
Yair Kukielka
2
Apakah mungkin untuk memiliki direktori SIBLING untuk digambar, dengan fungsionalitas yang dapat digambar? Jadi, res / tank / drawble- [hdpi .. etc] dan seterusnya?
Fattie

Jawaban:

546

Tidak, mekanisme sumber daya tidak mendukung subfolder di direktori yang dapat digambar, jadi ya - Anda perlu menjaga hierarki tetap datar.

Tata letak direktori yang Anda tampilkan tidak akan menghasilkan gambar yang tersedia.

Dari percobaan saya sendiri, tampaknya memiliki subfolder dengan item apa pun di dalamnya, di dalam res/drawablefolder, akan menyebabkan kompiler sumber daya gagal - mencegah R.javafile dihasilkan secara benar.

Reto Meier
sumber
136
Pada Android 2.2, ini tidak menyebabkan kesalahan kompiler, tetapi setiap subdirektori diabaikan ketika membuat kelas R. Ini sangat menyebalkan, dan membuatnya sulit untuk mengelola proyek yang lebih besar. = /
Nik Reiman
70
Setuju. Mereka harus datang dengan solusi yang lebih baik mendukung sub-folder. Itu tidak sulit.
znq
13
Mudah-mudahan ini akan segera teratasi, saya punya lebih dari 100 aset, dan bahkan kemudian saya membuat kode beberapa dari mereka. Total night mare berusaha mengelola proyek yang sedikit rumit.
Emile
14
Ini adalah Masalah terkait dalam pelacak masalah Android: code.google.com/p/android/issues/detail?id=2018
espinchi
44
kutukan kamu android
whitneyland
149

Solusi yang saya gunakan (dan yang disukai oleh Android) adalah mengganti garis bawah untuk garis miring, jadi struktur Anda akan terlihat seperti ini:

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

Pendekatan mengharuskan Anda untuk cermat dalam penamaan Anda dan tidak membuatnya lebih mudah untuk bertengkar file sendiri (jika Anda memutuskan bahwa minuman dan sandwich harus benar-benar semua " food", Anda harus melakukan perubahan nama massal daripada hanya memindahkannya ke direktori); tetapi kompleksitas logika pemrograman Anda tidak terlalu buruk dibandingkan dengan struktur folder yang setara.

Situasi ini memang menyebalkan. Android adalah campuran tas keputusan desain yang indah dan mengerikan. Kami hanya bisa berharap untuk bagian yang terakhir untuk disingkirkan dengan tergesa-gesa :)

Cheezmeister
sumber
31
Hanya perhatikan bahwa huruf kapital tidak diperbolehkan dalam folder yang dapat digambar. Saya mendapatkan kesalahan: "Nama file tidak valid: harus mengandung hanya [a-z0-9_.]"
Jason Axelson
5
1 untuk "tas campuran dari keputusan desain yang indah dan mengerikan"
Brent Faust
1
Solusi yang sulit: "apa yang harus Anda lakukan agar tidak menjadi benar-benar gila". Menggelikan hanya terbatas pada satu direktori.
RichieHH
35

Sebenarnya, di Android Studio itu mungkin. Anda dapat memiliki sumber daya bersarang seperti yang ditunjukkan di sini :

masukkan deskripsi gambar di sini

Ada juga plugin untuk mengelompokkan sumber daya di sini .

pengembang android
sumber
Hai, pengembang @android! Saya sudah mencoba menambahkan ini ke file build.gradle: sourceSets {main {res {srcDir 'src / main / res / drawable / ic-toggle'}}}, tapi saya punya "Uri tidak terdaftar" untuk xmlns : android = " schemas.android.com/apk/res/android . Apa yang bisa terjadi?
AlexKost
@AlexKost Saya benar-benar mencoba ini hanya sekali. Saya tidak cukup berpengalaman untuk membantu. Maaf.
pengembang android
@RahulMandaliya Meskipun mungkin, saya sarankan untuk tidak menggunakannya.
pengembang android
@androiddeveloper Mengapa tidak?
Josh Hansen
1
@ JoshHansen Ini berantakan.
Pengembang Android
34

Ya - itu payah :) Namun Anda dapat menggunakan folder aset dan memiliki sub direktori di sana dan memuat gambar seperti itu.

dijipiji
sumber
6
masalahnya bukan hanya untuk folder yang dapat digambar tetapi juga untuk folder tata letak :( Folder tata letak saya berisi lebih dari 100 file xml, dan sulit bagi saya untuk membuka tata letak xml yang tepat dalam hal ini.
anticafe
Appart untuk keberatan lainnya, sumber daya dapat dengan mudah dilokalkan tetapi AFAIK tidak ada mekanisme yang dibangun untuk aset.
Fran Marzoa
@anticafe gunakan "Pergi ke sumber daya" di IDE Anda (Eclipse: CTRL + SHIFT + R, IDEA / Android Studio: CTRL + SHIFT + N)
TWiStErRob
23

Gunakan folder aset.

Kode sampel:

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

image = BitmapFactory.decodeStream(is);
milkia
sumber
5
Satu-satunya masalah dengan metode ini adalah bahwa ada BANYAK pekerjaan rumah yang terlibat dengan menggunakan bitmap. Sistem sumber daya Android melakukan pekerjaan manajemen memori yang jauh lebih baik. Mengapa Anda membangun kembali sistem manajemen memori ketika Android sudah melakukannya? Terutama jika dia memiliki 100+ gambar, itu banyak memuat dan melepaskan bitmap.
Pdt Tyler
18
Ini adalah masalah nyata adalah Anda berencana untuk melokalkan aplikasi Anda, juga jika Anda memiliki sumber daya yang berbeda untuk kepadatan layar yang berbeda, jadi itu bukan solusi, hanya solusi yang hanya berlaku untuk beberapa kasus.
Fran Marzoa
1
Saya perlu memberikan komentar @Fran setidaknya seribu
suara positif
22

Saya telah menulis sebuah plugin gerhana yang memungkinkan untuk membuat subfolder virtual dengan memisahkan nama file dengan dua garis bawah __. Proyek ini masih dalam tahap awal, tetapi jangan khawatir itu tidak akan merusak IDE Anda

detail lebih lanjut dapat ditemukan di sini, silakan garpu dan kirim permintaan tarik:

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

masukkan deskripsi gambar di sini

Kirill Kulakov
sumber
2
Bagus! Adakah peluang untuk memindahkan ini ke Android Studio juga?
BVB
1
Saat ini saya bahkan tidak menggunakan android studio, jadi saya kira, kita harus menunggu beberapa berpengalaman untuk port itu.
Kirill Kulakov
9

Saya suka menggunakan skrip sederhana untuk meratakan struktur direktori terorganisir yang disediakan oleh desainer untuk sesuatu yang dapat digunakan untuk menghasilkan file R.

Jalankan dengan jalur saat ini di 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
Ren
sumber
1
Skrip Anda tidak akan berfungsi jika ada sub folder di bawah folder. Saya pikir Anda perlu mengganti semua '/' dengan '_' dalam $ {dir}.
Seunghoon
9

Di studio android dengan gradle Anda dapat memiliki beberapa sumber direktur yang akan memungkinkan Anda untuk memisahkan sumber daya. Sebagai contoh:

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

Namun nama tidak boleh bertabrakan yang berarti Anda masih perlu memiliki nama seperti sandwiches_tunaOnRye tetapi Anda akan dapat memiliki bagian terpisah untuk semua sandwich Anda.

Ini memungkinkan Anda untuk menyimpan sumber daya di berbagai struktur (berguna untuk konten yang dibuat secara otomatis seperti actionbargenerator)

Alec Holmes
sumber
4

Salah satu cara untuk mengatasi sebagian masalah adalah dengan menggunakan akhiran Tingkat API. Saya menggunakan res / layout-v1, res / layout-v2 dll untuk mengadakan beberapa sub proyek di apk yang sama. Mekanisme ini dapat digunakan untuk semua jenis sumber daya.

Jelas, ini hanya dapat digunakan jika Anda menargetkan level API di atas res / layout-v? Anda menggunakan.

Juga, perhatikan bug di Android 1.5 dan 1.6. Lihat dokumentasi Andoroid tentang akhiran Level API .

OferR
sumber
Kepada siapa pun yang menurunkan jawaban ini: Bisakah Anda menjelaskan alasannya? Mekanisme ini, meskipun tidak cantik, bekerja dengan baik untuk saya.
OferR
4

Dengan munculnya sistem perpustakaan, membuat perpustakaan per set besar aset bisa menjadi solusi.

Ini masih bermasalah karena kita harus menghindari menggunakan nama yang sama dalam semua aset tetapi menggunakan skema awalan per pustaka akan membantu dengan itu.

Ini tidak sesederhana membuat folder tetapi itu membantu menjaga hal-hal tetap waras ...

shi
sumber
Ya, saya pikir ini bagus. Jika saya menambahkan flag negara ke folder drawable-ldpi etc. saya maka mereka akan kebanjiran. Saya pikir membuat proyek perpustakaan untuk semua sumber daya generik akan membantu mengurangi kekacauan dalam proyek yang sedang Anda kerjakan secara aktif. Terkejut Anda hanya memiliki 1 suara positif.
Tom
3

Ada solusi untuk situasi ini: Anda dapat membuat resVectorfolder (misalnya) pada level yang sama dengan resfolder default . Di sana Anda dapat menambahkan drawable-xxxfolder sumber daya apa pun di sana:

resVector
-drawable
-layout
-color

Setelah itu yang Anda butuhkan hanyalah menambahkan

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

ke dalam build.gradlefile Anda (di dalam android { }).

Anton Derevyanko
sumber
Sayangnya mereka bergabung bersama di panel proyek di Android Studio saat menggunakan perspektif "Android" :(
AjahnCharles
@ AjahnCharles - Saya lebih suka untuk tidak menggunakan perspektif ini sama sekali (lagi pula - saya selalu bekerja di 'mode bebas gangguan') ... Tapi Anda benar - "Android" menggabungkan semuanya.
Anton Derevyanko
1

Ini bukan metode yang sempurna. Anda harus menerapkan cara yang sama yang ditampilkan di sini .

Anda juga dapat memanggil gambar di bawah folder melalui kode yang dapat Anda gunakan

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

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

Bukan milik saya, tetapi saya menemukan utas ini ketika mencari masalah ini, jika Anda menggunakan Android Studio dan sistem Gradle Build-nya cukup mudah, tidak ada plugin yang diperlukan.

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

Captnwalker1
sumber
1

Gradle dengan Android Studio dapat melakukannya dengan cara ini ( tautan ).

Itu ada di paragraf "Mengkonfigurasi Struktur"

sourceSets {
 main {
    java {
        srcDir 'src/java'
    }
    resources {
        srcDir 'src/resources'
    }
 }
}
pengguna3290180
sumber
1

buat folder di main. seperti: 'res_notification_btn'

dan buat folder pohon masuk. seperti 'drawable' atau 'layout'

lalu di 'build.gradle' tambahkan ini

sourceSets
            {
                main
                {
                    res
                    {
                        srcDirs = ['src/main/res_notification_btn', 'src/main/res']
                      or
                        srcDir 'src/main/res_notification_btn'
                    }
                }
            }
Ali Bagheri
sumber
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
sumber
Semua ini dilakukan adalah mengotomatiskan solusi yang disarankan oleh Cheezmeister. Ini bekerja untuk saya ... mau menjelaskan downvote?
Blake Miller
0

aset / Anda dapat menggunakannya untuk menyimpan file aset mentah. File yang Anda simpan di sini dikompilasi menjadi file .apk apa adanya, dan nama file asli dipertahankan. Anda dapat menavigasi direktori ini dengan cara yang sama seperti sistem file khas menggunakan URI dan membaca file sebagai aliran byte menggunakan AssetManager. Sebagai contoh, ini adalah lokasi yang bagus untuk tekstur dan data game. http://developer.android.com/tools/projects/index.html

Alex M.
sumber
0

Subdirektori tidak diizinkan, sumber daya harus mengandung hanya [a-z0-9_.].

Tidak, Anda memiliki huruf besar, dan tidak ada garis miring.

Ferhat Aslan
sumber
-3
  1. Klik kanan pada Drawable
  2. Pilih Baru ---> Direktori
  3. Masukkan nama direktori. Misalnya: logo.png (lokasi sudah akan menampilkan folder yang dapat digambar secara default)
  4. Salin dan tempel gambar langsung ke folder yang dapat digambar. Saat menempelkan Anda mendapatkan opsi untuk memilih mdpi / xhdpi / xxhdpi dll untuk masing-masing gambar dari daftar. Pilih opsi yang sesuai dan masukkan nama gambar. Pastikan untuk menjaga nama yang sama dengan nama direktori yaitu logo.png
  5. Lakukan hal yang sama untuk gambar yang tersisa. Semuanya akan ditempatkan di bawah folder utama logo.png.
Afreen Hasheem Siraj
sumber