ไดเรกทอรี drawable Android สามารถมีไดเรกทอรีย่อยได้หรือไม่?


496

ในเอกสารประกอบ Android SDK ตัวอย่างทั้งหมดที่ใช้กับไวยากรณ์ @ drawable / my_image xml ระบุที่อยู่ของรูปภาพโดยตรงที่เก็บไว้ในไดเรกทอรี res / drawable ในโครงการของฉัน

ฉันสงสัยว่าถ้าไม่ชัดเจนที่จะสร้างไดเรกทอรีย่อยภายในไดเรกทอรีที่สามารถดึงข้อมูลได้

ตัวอย่างเช่นถ้าฉันมีรูปแบบไดเรกทอรีต่อไปนี้:

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

ฉันขออ้างอิงภาพแซนวิชทูน่าสลัดเป็น @ drawable / sandwiches / tunaOnRye

หรือฉันจะต้องรักษาลำดับชั้นให้คงอยู่ในไดเรกทอรีที่วาดได้


16
โปรดทราบว่าไม่อนุญาตให้ใช้อักษรตัวพิมพ์ใหญ่ในไดเรกทอรี res
Tyler

1
คุณสามารถทำได้ด้วย Gradle: stackoverflow.com/a/19859379
Yair Kukielka

2
เป็นไปได้หรือไม่ที่จะมีไดเรกทอรีSIBLING ที่สามารถวาดได้ด้วยการใช้งานได้ ดังนั้นความละเอียด / ถัง / drawble- [hdpi .. ฯลฯ ] และอื่น ๆ ?
Fattie

คำตอบ:


545

ไม่กลไกทรัพยากรไม่รองรับโฟลเดอร์ย่อยในไดเรกทอรี drawable ดังนั้นใช่ - คุณต้องทำให้ลำดับชั้นนั้นแบน

เลย์เอาต์ของไดเรกทอรีที่คุณแสดงจะทำให้ไม่มีภาพที่ใช้ได้

จากการทดลองของฉันเองดูเหมือนว่าการมีโฟลเดอร์ย่อยที่มีรายการใด ๆ อยู่ภายในres/drawableโฟลเดอร์จะทำให้คอมไพเลอร์ทรัพยากรล้มเหลวทำให้R.javaไฟล์ไม่ถูกสร้างขึ้นอย่างถูกต้อง


135
ในฐานะของ Android 2.2 สิ่งนี้ไม่ได้ทำให้เกิดข้อผิดพลาดในการรวบรวม แต่ไดเรกทอรีย่อยใด ๆ จะถูกละเว้นเมื่อสร้างคลาส R สิ่งนี้แย่มากและทำให้ยากต่อการจัดการโครงการขนาดใหญ่ = /
Nik Reiman

69
เห็นด้วยอย่างสิ้นเชิง. พวกเขาต้องการวิธีแก้ปัญหาที่ดีกว่าที่สนับสนุนโฟลเดอร์ย่อย มันไม่ยากอย่างนั้น
znq

13
หวังว่าเรื่องนี้จะได้รับการแก้ไขเร็ว ๆ นี้ฉันมีสินทรัพย์มากกว่า 100 รายการและแม้กระทั่งฉันก็เขียนบางส่วนออกมา ยอดรวมกลางคืนพยายามที่จะจัดการโครงการที่ซับซ้อนใด ๆ
Emile

14
นี่คือปัญหาที่เกี่ยวข้องในตัวติดตามปัญหา Android: code.google.com/p/android/issues/detail?id=2018
espinchi

44
สาปแช่งคุณ android
whitneyland

149

วิธีแก้ปัญหาที่ฉันใช้ (และ Android ตัวเดียวดูเหมือนจะเป็นที่นิยม) คือการแทนที่ขีดล่างสำหรับเครื่องหมายทับด้านหน้าดังนั้นโครงสร้างของคุณจะมีลักษณะดังนี้:

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

วิธีการดังกล่าวทำให้คุณต้องใช้ความพิถีพิถันในการตั้งชื่อและไม่ได้ง่ายกว่าที่คุณจะบีบไฟล์เอง (ถ้าคุณตัดสินใจว่าเครื่องดื่มและแซนด์วิชควรจะเป็น " food" จริง ๆ คุณต้องเปลี่ยนชื่อเป็นจำนวนมาก ย้ายพวกเขาไปยังไดเรกทอรี); แต่ความซับซ้อนของตรรกะการเขียนโปรแกรมของคุณก็ไม่ได้รับผลกระทบเช่นกันนักเมื่อเทียบกับโครงสร้างโฟลเดอร์ที่เทียบเท่า

สถานการณ์นี้แย่จริงๆ Android เป็นกระเป๋าที่ผสมผสานการตัดสินใจการออกแบบที่ยอดเยี่ยมและน่ากลัว เราสามารถหวังว่าส่วนหลังจะได้รับการกำจัดด้วยความรีบเร่งทั้งหมด :)


31
เพียงแค่ทราบว่าไม่อนุญาตให้ใช้ตัวอักษรพิมพ์ใหญ่ในโฟลเดอร์ drawable ฉันได้รับข้อผิดพลาด: "ชื่อไฟล์ไม่ถูกต้อง: ต้องมีเพียง [a-z0-9_.]"
Jason Axelson

5
+1 สำหรับ "การตัดสินใจเกี่ยวกับการออกแบบที่ยอดเยี่ยมและแย่"
Brent Faust

1
วิธีแก้ปัญหาแทบจะไม่: ค่อนข้าง "สิ่งที่คุณควรทำเพื่อที่จะไม่ไปบ้าอย่างสมบูรณ์" มันน่าหัวเราะที่ถูก จำกัด ไว้ที่หนึ่งไดเรกทอรี
RichieHH

35

ที่จริงแล้วบน Android Studio มันเป็นไปได้ คุณสามารถมีทรัพยากรที่ซ้อนกันดังที่แสดงไว้ที่นี่ :

ป้อนคำอธิบายรูปภาพที่นี่

นอกจากนี้ยังมีปลั๊กอินสำหรับจัดกลุ่มทรัพยากรที่นี่ที่นี่


สวัสดีนักพัฒนา @android! ฉันได้พยายามเพิ่มสิ่งนี้ลงในไฟล์ build.gradle: sourceSets {main {res {srcDir 'src / main / res / drawable / ic-toggle'}}} แต่ฉันได้รับ "Uri ไม่ได้ลงทะเบียน" สำหรับ xmlns : android = " schemas.android.com/apk/res/androidอาจมีกรณีอะไรบ้าง?
AlexKost

@AlexKost ฉันลองแค่ครั้งเดียวจริง ๆ ฉันไม่ได้มีประสบการณ์เพียงพอที่จะช่วยเหลือ ขอโทษ
นักพัฒนา android

@RahulMandaliya แม้ว่าจะเป็นไปได้ แต่ฉันแนะนำไม่ให้ใช้
นักพัฒนา android

@androiddeveloper ทำไมล่ะ
Josh Hansen

1
@JoshHansen มันยุ่ง
นักพัฒนา Android

34

ใช่ - มันดูด :) อย่างไรก็ตามคุณสามารถใช้โฟลเดอร์สินทรัพย์และมีไดเรกทอรีย่อยอยู่ในนั้นและโหลดภาพด้วยวิธีดังกล่าว


6
ปัญหาคือไม่เพียง แต่สำหรับโฟลเดอร์ drawable แต่ยังสำหรับโฟลเดอร์รูปแบบ :( โฟลเดอร์รูปแบบของฉันที่มีมากกว่า 100 ไฟล์ XML, และมันเป็นเรื่องยากสำหรับผมที่จะเปิดรูปแบบ XML ที่ถูกต้องในเรื่องนี้.
anticafe

Appart สำหรับการคัดค้านอื่น ๆ ทรัพยากรอาจถูกแปลเป็นภาษาท้องถิ่นได้ง่าย แต่ AFAIK ไม่มีกลไกที่สร้างขึ้น l10n สำหรับสินทรัพย์
Fran Marzoa

@anticafe ใช้ "Go to resource" ใน IDE ของคุณ (Eclipse: CTRL + SHIFT + R, IDEA / Android Studio: CTRL + SHIFT + N)
TWiStErRob

23

ใช้โฟลเดอร์ทรัพย์สิน

รหัสตัวอย่าง:

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

image = BitmapFactory.decodeStream(is);

5
ปัญหาเดียวของวิธีนี้คือมีการบ้านจำนวนมากที่เกี่ยวข้องกับการใช้บิตแมป ระบบทรัพยากรของ Android ทำงานได้ดีขึ้นมากในการจัดการหน่วยความจำ ทำไมคุณต้องสร้างระบบการจัดการหน่วยความจำใหม่เมื่อ Android ทำแล้ว? ถ้าเขามีภาพมากกว่า 100 ภาพนั่นเป็นจำนวนมากที่โหลดและปล่อยบิตแมป
Rev Tyler

18
นี่เป็นปัญหาที่แท้จริงคือคุณวางแผนที่จะโลคัลไลซ์แอปพลิเคชันของคุณและถ้าคุณมีทรัพยากรที่แตกต่างกันสำหรับความหนาแน่นของหน้าจอที่แตกต่างกันดังนั้นจึงไม่ใช่วิธีแก้ปัญหา
Fran Marzoa

1
ฉันต้องการที่จะให้ความคิดเห็น @Fran 's อย่างน้อยพัน upvotes :)
HGPB

22

ฉันได้เขียนปลั๊กอิน eclipse ซึ่งอนุญาตให้สร้างโฟลเดอร์ย่อยเสมือนโดยแยกชื่อไฟล์ด้วยขีดล่างสองอัน __อัน โครงการอยู่ในช่วงเริ่มต้น แต่ไม่ต้องกังวลว่าจะไม่ทำให้ IDE ของคุณเสียหาย

รายละเอียดเพิ่มเติมสามารถดูได้ที่นี่อย่าลังเลที่จะแยกและส่งคำขอดึง:

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

ป้อนคำอธิบายรูปภาพที่นี่


2
ดี! มีโอกาสที่จะย้ายข้อมูลนี้ไปยัง Android Studio ด้วยหรือไม่
BVB

1
ขณะนี้ฉันไม่ได้ใช้ android studio ดังนั้นฉันเดาว่าเราจะต้องรอให้มีประสบการณ์ในการย้ายพอร์ต
Kirill Kulakov

9

ฉันชอบที่จะใช้สคริปต์ง่าย ๆ เพื่อทำให้โครงสร้างไดเรกทอรีที่เป็นระเบียบจัดทำโดยนักออกแบบเพื่อสิ่งที่สามารถใช้ในการสร้างไฟล์ R

รันด้วยพา ธ ปัจจุบันใน 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
สคริปต์ของคุณจะไม่ทำงานหากมีโฟลเดอร์ย่อยภายใต้โฟลเดอร์ ฉันคิดว่าคุณต้องแทนที่ '/' ทั้งหมดด้วย '_' ใน $ {dir}
ซึงฮุน

9

ใน android studio ที่มี gradle คุณสามารถมีผู้กำกับหลายคนที่จะอนุญาตให้คุณแยกทรัพยากร ตัวอย่างเช่น:

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

อย่างไรก็ตามชื่อจะต้องไม่ชนกันซึ่งหมายความว่าคุณยังจะต้องมีชื่อเช่น sandwiches_tunaOnRye แต่คุณจะสามารถแยกส่วนสำหรับแซนด์วิชทั้งหมดของคุณได้

สิ่งนี้ช่วยให้คุณสามารถจัดเก็บทรัพยากรของคุณในโครงสร้างที่แตกต่างกัน (มีประโยชน์สำหรับเนื้อหาที่สร้างขึ้นอัตโนมัติเช่น actionbargenerator)


4

วิธีหนึ่งในการแก้ไขปัญหาบางส่วนคือใช้ส่วนต่อท้ายระดับ API ฉันใช้ res / layout-v1, res / layout-v2 และอื่น ๆ เพื่อเก็บหลายโครงการย่อยใน apk เดียวกัน กลไกนี้สามารถใช้กับทรัพยากรทุกประเภท

เห็นได้ชัดว่าสิ่งนี้สามารถใช้งานได้หากคุณกำหนดเป้าหมายระดับ API เหนือ res / layout-v เท่านั้น คุณกำลังใช้

นอกจากนี้ระวังข้อผิดพลาดใน Android 1.5 และ 1.6 ดูเอกสาร Andoroid เกี่ยวกับปัจจัยระดับ


สำหรับผู้ที่ลดระดับคำตอบนี้: คุณอธิบายได้ไหม กลไกนี้แม้ว่าจะไม่สวย แต่ก็ใช้ได้ดีสำหรับฉัน
OferR

4

ด้วยการกำเนิดของระบบห้องสมุดการสร้างห้องสมุดต่อสินทรัพย์ชุดใหญ่อาจเป็นทางออก

ยังคงเป็นปัญหาอยู่เนื่องจากต้องหลีกเลี่ยงการใช้ชื่อเดียวกันภายในเนื้อหาทั้งหมด แต่การใช้คำนำหน้าแบบแผนต่อไลบรารีควรช่วยด้วย

มันไม่ง่ายอย่างที่จะสามารถสร้างโฟลเดอร์ แต่ช่วยรักษาสิ่งที่มีเหตุผล ...


ใช่ฉันคิดว่ามันดี ถ้าฉันเพิ่มธงประเทศลงในโฟลเดอร์ drawable-ldpi ฯลฯ ของฉันพวกเขาจะล้นมือ ฉันคิดว่าการสร้างโครงการห้องสมุดสำหรับทรัพยากรทั่วไปทั้งหมดจะช่วยลดความยุ่งเหยิงในโครงการที่คุณกำลังทำอยู่ ประหลาดใจคุณมีเพียง 1 upvote
Tom

3

มีวิธีแก้ไขสำหรับสถานการณ์นี้: คุณสามารถสร้างresVectorโฟลเดอร์ (ตัวอย่าง) ในระดับเดียวกับresโฟลเดอร์เริ่มต้น ที่นั่นคุณสามารถเพิ่มdrawable-xxxโฟลเดอร์ทรัพยากรที่นั่น:

resVector
-drawable
-layout
-color

หลังจากนั้นสิ่งที่คุณต้องการคือการเพิ่ม

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

ลงในbuild.gradleไฟล์ของคุณ(ภายในandroid { })


น่าเศร้าที่พวกเขารวมเข้าด้วยกันในแผงโครงการใน Android Studio เมื่อใช้มุมมอง "Android" :(
AjahnCharles

@AjahnCharles - ฉันไม่ต้องการใช้มุมมองนี้เลย (ต่อไป - ฉันมักจะทำงานที่ 'โหมดฟรีฟุ้งซ่าน') ... แต่คุณพูดถูก - "Android" ผสานทุกอย่างเข้าด้วยกัน
Anton Derevyanko

1

นี่ไม่ใช่วิธีการที่สมบูรณ์แบบ คุณจะต้องดำเนินการในลักษณะเดียวกันซึ่งเป็นจอแสดงผลที่นี่

คุณยังสามารถโทรหารูปภาพภายใต้โฟลเดอร์ผ่านรหัสที่คุณสามารถใช้ได้

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

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

1

ไม่ใช่ของฉัน แต่ฉันพบเธรดนี้เมื่อค้นหาปัญหานี้หากคุณใช้ระบบ Android Studio และ Gradle Build มันค่อนข้างง่ายไม่จำเป็นต้องใช้ปลั๊กอินเพียงแค่การสร้างไฟล์เล็ก ๆ น้อย ๆ

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


1

Gradle กับ Android Studio สามารถทำได้ด้วยวิธีนี้ ( ลิงก์ )

มันอยู่ในย่อหน้า "การกำหนดค่าโครงสร้าง"

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

1

สร้างโฟลเดอร์ในหลัก ไลค์: 'res_notification_btn'

และสร้างโฟลเดอร์ทรีเช่น 'drawable' หรือ 'layout'

จากนั้นใน 'build.gradle' เพิ่มสิ่งนี้

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

ทั้งหมดนี้ทำโดยอัตโนมัติวิธีแก้ปัญหาที่แนะนำโดย Cheezmeister มันทำงานได้สำหรับฉัน ... สนใจที่จะอธิบาย downvote หรือไม่
Blake Miller


0

asset / คุณสามารถใช้มันเพื่อจัดเก็บไฟล์สินทรัพย์ดิบ ไฟล์ที่คุณบันทึกที่นี่จะถูกรวบรวมเป็นไฟล์. apk ตามที่เป็นอยู่และชื่อไฟล์ดั้งเดิมจะถูกเก็บรักษาไว้ คุณสามารถนำทางไดเรกทอรีนี้ในลักษณะเดียวกับระบบไฟล์ทั่วไปโดยใช้ URIs และอ่านไฟล์ในรูปแบบของไบต์โดยใช้ AssetManager ตัวอย่างเช่นนี่เป็นตำแหน่งที่ดีสำหรับพื้นผิวและข้อมูลเกม http://developer.android.com/tools/projects/index.html


0

ไดเรกทอรีย่อยไม่ได้รับอนุญาตทรัพยากรต้องมีเพียง [a-z0-9_]

ไม่มีคุณมีตัวอักษรตัวพิมพ์ใหญ่และไม่มีเครื่องหมายสแลช


-3
  1. คลิกขวาที่ Drawable
  2. เลือกใหม่ ---> ไดเรกทอรี
  3. ป้อนชื่อไดเรกทอรี เช่น logo.png (ตำแหน่งจะแสดงโฟลเดอร์ที่สามารถดึงได้ตามค่าเริ่มต้น)
  4. คัดลอกและวางภาพโดยตรงลงในโฟลเดอร์ drawable ขณะวางคุณจะได้รับตัวเลือกให้เลือก mdpi / xhdpi / xxhdpi ฯลฯ สำหรับแต่ละภาพจากรายการ เลือกตัวเลือกที่เหมาะสมและป้อนชื่อของภาพ ตรวจสอบให้แน่ใจว่าได้ใช้ชื่อเดียวกันกับชื่อไดเรกทอรีเช่น logo.png
  5. ทำเช่นเดียวกันกับภาพที่เหลือ ทั้งหมดจะถูกวางไว้ใต้ logo.png โฟลเดอร์หลัก
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.