Thư mục drawable của Android có thể chứa các thư mục con không?


497

Trong tài liệu SDK của Android, tất cả các ví dụ được sử dụng với cú pháp @ drawable / my_image xml trực tiếp giải quyết các hình ảnh được lưu trữ trong thư mục res / drawable trong dự án của tôi.

Tôi tự hỏi nếu nó rõ ràng là không ổn để tạo một thư mục con trong thư mục drawable.

Ví dụ: nếu tôi có bố cục thư mục sau:

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

Tôi có thể tham khảo hình ảnh của một chiếc bánh sandwich salad cá ngừ là @ drawable / sandwiches / tunaOnRye

Hoặc tôi phải giữ cấu trúc phân cấp trong thư mục drawable.


16
Xin lưu ý rằng chữ in hoa không được phép trong thư mục res.
Tyler

1
Bạn chỉ có thể làm điều này với Gradle: stackoverflow.com/a/19859379
Yair Kukielka

2
Có thể có các thư mục SIBLING để drawable, với chức năng drawable? Vì vậy, res / tank / drawble- [hdpi .. vv] và như vậy?
Fattie

Câu trả lời:


546

Không, cơ chế tài nguyên không hỗ trợ các thư mục con trong thư mục có thể vẽ được, vì vậy, có - bạn cần giữ cấu trúc phân cấp đó bằng phẳng.

Bố cục thư mục bạn hiển thị sẽ không dẫn đến hình ảnh nào.

Từ các thử nghiệm của riêng tôi, dường như việc có một thư mục con với bất kỳ mục nào trong đó, trong res/drawablethư mục, sẽ khiến trình biên dịch tài nguyên không thành công - ngăn không cho R.javatệp được tạo chính xác.


136
Kể từ Android 2.2, điều này không gây ra lỗi trình biên dịch, nhưng mọi thư mục con đều bị bỏ qua khi tạo lớp R. Điều này thực sự hút, và làm cho nó khó khăn để quản lý các dự án lớn hơn. = /
Nik Reiman

70
Hoàn toàn đồng ý. Họ cần đưa ra một giải pháp tốt hơn để hỗ trợ các thư mục con. Nó không thể khó như vậy.
znq

13
Hy vọng điều này sẽ sớm được giải quyết, tôi đã có hơn 100 tài sản và thậm chí sau đó tôi đã mã hóa một số trong số chúng. Tổng số đêm cố gắng để quản lý bất kỳ dự án phức tạp biên.
Emile

14
Đây là Vấn đề tương ứng trong trình theo dõi sự cố của Android: code.google.com/p/android/issues/detail?id=2018
đặc biệt là

44
nguyền rủa bạn android
whitneyland

149

Cách giải quyết mà tôi đang sử dụng (và bản thân Android dường như ủng hộ) về cơ bản là thay thế dấu gạch dưới cho dấu gạch chéo về phía trước, do đó cấu trúc của bạn sẽ trông giống như thế này:

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

Cách tiếp cận đòi hỏi bạn phải tỉ mỉ trong việc đặt tên và không làm cho việc sắp xếp các tệp dễ dàng hơn nhiều (nếu bạn quyết định rằng đồ uống và bánh sandwich thực sự nên là " food", bạn phải đổi tên hàng loạt thay vì đơn giản di chuyển chúng vào thư mục); nhưng độ phức tạp của logic lập trình của bạn không bị ảnh hưởng quá nhiều so với cấu trúc thư mục tương đương.

Tình hình này thực sự hút. Android là một túi hỗn hợp của các quyết định thiết kế tuyệt vời và khủng khiếp. Chúng ta chỉ có thể hy vọng phần sau sẽ được loại bỏ với tất cả sự vội vàng :)


31
Chỉ cần lưu ý rằng chữ in hoa không được phép trong thư mục drawable. Tôi gặp lỗi: "Tên tệp không hợp lệ: chỉ chứa [a-z0-9_.]"
Jason Axelson

5
+1 cho "túi hỗn hợp của các quyết định thiết kế tuyệt vời và khủng khiếp"
Brent Faust

1
Rất khó để giải quyết: thay vì "những gì bạn nên làm để không phát điên hoàn toàn". Thật lố bịch khi bị giới hạn trong một thư mục.
RichieHH

35

Trên thực tế, trên Android Studio là có thể. Bạn có thể có các tài nguyên lồng nhau như được hiển thị ở đây :

nhập mô tả hình ảnh ở đây

Ngoài ra còn có một plugin để tài nguyên nhóm ở đây .


Xin chào, nhà phát triển @android! Tôi đã cố gắng thêm tệp này vào tệp build.gradle: sourceSets {main {res {srcDir 'src / main / res / drawable / ic-toggle'}}}, nhưng tôi đã nhận được "Uri chưa được đăng ký" cho xmlns : android = " schemas.android.com/apk/res/android . Điều gì có thể xảy ra?
AlexKost

@AlexKost Tôi thực sự đã thử điều này chỉ một lần. Tôi không có kinh nghiệm với nó đủ để giúp đỡ. Lấy làm tiếc.
nhà phát triển Android

@RahulMandaliya Mặc dù có thể, tôi khuyên bạn không nên sử dụng nó.
nhà phát triển Android

@androiddeveloper Tại sao không?
Josh Hansen

1
@JoshHansen Nó lộn xộn.
nhà phát triển Android

34

Có - nó thật tệ :) Tuy nhiên, bạn có thể sử dụng thư mục tài sản và có các thư mục con trong đó và tải hình ảnh theo cách đó.


6
vấn đề không chỉ đối với thư mục có thể vẽ mà còn đối với thư mục bố cục :( Thư mục bố cục của tôi chứa hơn 100 tệp xml và thật khó để tôi mở bố cục xml đúng trong này.
anticafe

Đối với các phản đối khác, tài nguyên có thể được bản địa hóa dễ dàng nhưng AFAIK không có cơ chế xây dựng l10n cho tài sản.
Fran Marzoa

@anticafe sử dụng "Chuyển đến tài nguyên" trong IDE của bạn (Eclipse: CTRL + SHIFT + R, IDEA / Android Studio: CTRL + SHIFT + N)
TWiStErRob

23

Sử dụng thư mục tài sản.

mã mẫu:

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

image = BitmapFactory.decodeStream(is);

5
Vấn đề duy nhất với phương pháp này là có rất nhiều bài tập về nhà liên quan đến việc sử dụng bitmap. Hệ thống tài nguyên của Android thực hiện công việc quản lý bộ nhớ tốt hơn nhiều. Tại sao bạn sẽ xây dựng lại một hệ thống quản lý bộ nhớ khi Android đã làm điều đó? Đặc biệt nếu anh ta có hơn 100 hình ảnh, đó là rất nhiều tải và phát hành bitmap.
Rev Tyler

18
Đây là một vấn đề thực sự là bạn có kế hoạch bản địa hóa ứng dụng của mình, ngoài ra nếu bạn có các tài nguyên khác nhau cho các mật độ màn hình khác nhau, thì đó không phải là một giải pháp, chỉ là một cách giải quyết hợp lệ cho một số trường hợp.
Fran Marzoa

1
Tôi cần đưa ra nhận xét của @Fran ít nhất một nghìn lượt
upvote

22

Tôi đã viết một plugin nhật thực cho phép tạo thư mục con ảo bằng cách tách tên tệp với hai dấu gạch dưới __. Dự án đang ở giai đoạn đầu, nhưng đừng lo, nó sẽ không làm sập IDE của bạn

biết thêm chi tiết có thể được tìm thấy ở đây, vui lòng rẽ nhánh và gửi yêu cầu kéo:

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

nhập mô tả hình ảnh ở đây


2
Đẹp! Bất kỳ cơ hội nào để chuyển điều này sang Android Studio là tốt?
BVB

1
Tôi hiện thậm chí không sử dụng android studio, vì vậy tôi đoán, chúng tôi sẽ phải chờ một số người có kinh nghiệm để chuyển nó.
Kirill Kulakov

9

Tôi thích sử dụng một tập lệnh đơn giản để làm phẳng cấu trúc thư mục có tổ chức được cung cấp bởi các nhà thiết kế cho một cái gì đó có thể được sử dụng để tạo tệp R.

Chạy với đường dẫn hiện tại trong 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
Tập lệnh của bạn sẽ không hoạt động nếu có các thư mục con trong các thư mục. Tôi nghĩ bạn cần thay thế tất cả '/' bằng '_' bằng $ {dir}.
Seunghoon

9

Trong studio android với gradle, bạn có thể có nhiều giám đốc nguồn cho phép bạn tách tài nguyên. Ví dụ:

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

Tuy nhiên, các tên không được va chạm, điều đó có nghĩa là bạn vẫn sẽ cần phải có các tên như sandwiches_tunaOnRye nhưng bạn sẽ có thể có một phần riêng biệt cho tất cả các bánh sandwich của bạn.

Điều này cho phép bạn lưu trữ tài nguyên của mình trong các cấu trúc khác nhau (hữu ích cho nội dung được tạo tự động, chẳng hạn như bộ tạo hành động)


4

Một cách để khắc phục một phần vấn đề là sử dụng hậu tố Cấp độ API. Tôi sử dụng res / layout-v1, res / layout-v2, v.v để giữ nhiều dự án phụ trong cùng một apk. Cơ chế này có thể được sử dụng cho tất cả các loại tài nguyên.

Rõ ràng, điều này chỉ có thể được sử dụng nếu bạn đang nhắm mục tiêu các cấp API trên độ phân giải / layout-v? bạn đang sử dụng.

Ngoài ra, xem ra lỗi trong Android 1.5 và 1.6. Xem tài liệu Andoroid về hậu tố Cấp API .


Cho bất cứ ai hạ cấp câu trả lời này: Bạn có thể giải thích tại sao? Cơ chế này, mặc dù không đẹp, hoạt động tốt cho tôi.
OferR

4

Với sự ra đời của hệ thống thư viện, việc tạo ra một thư viện trên một tập hợp tài sản lớn có thể là một giải pháp.

Vẫn còn vấn đề vì người ta phải tránh sử dụng cùng tên trong tất cả các tài sản nhưng sử dụng lược đồ tiền tố cho mỗi thư viện sẽ giúp ích cho điều đó.

Nó không đơn giản như có thể tạo các thư mục nhưng điều đó giúp giữ mọi thứ lành mạnh ...


Vâng, tôi nghĩ rằng điều này là tốt. Nếu tôi thêm cờ quốc gia vào các thư mục drawable-ldpi, v.v. thì chúng sẽ bị ngập. Tôi nghĩ rằng việc tạo một dự án thư viện cho tất cả các tài nguyên chung sẽ giúp giảm bớt sự lộn xộn trong dự án mà bạn đang tích cực làm việc. Ngạc nhiên là bạn chỉ có 1 upvote.
Tom

3

Có một cách giải quyết cho tình huống này: bạn có thể tạo resVectorthư mục (ví dụ) ở cùng cấp độ với resthư mục mặc định . Ở đó bạn có thể thêm bất kỳ drawable-xxxthư mục tài nguyên nào ở đó:

resVector
-drawable
-layout
-color

Sau đó, tất cả những gì bạn cần là thêm

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

vào build.gradletập tin của bạn (bên trong android { }).


Đáng buồn thay, họ hợp nhất với nhau trong bảng điều khiển dự án trong Android Studio khi sử dụng phối cảnh "Android" :(
AjahnCharles

@AjahnCharles - Tôi hoàn toàn không thích sử dụng phối cảnh này (dù sao đi nữa - tôi luôn làm việc ở 'chế độ miễn phí phân tâm') ... Nhưng bạn đã đúng - "Android" hợp nhất mọi thứ.
Anton Derevyanko

1

Đây không phải là phương pháp hoàn hảo. Bạn phải thực hiện theo cách tương tự được hiển thị ở đây .

Bạn cũng có thể gọi hình ảnh trong thư mục thông qua mã bạn có thể sử dụng

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

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

1

Không phải của tôi nhưng tôi đã tìm thấy chủ đề này khi tìm kiếm vấn đề này, nếu bạn sử dụng hệ thống Android Studio và Gradle Build thì khá dễ dàng, không cần plugin chỉ cần chỉnh sửa tệp xây dựng một chút

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


1

Gradle với Android Studio có thể làm theo cách này ( liên kết ).

Đó là trong đoạn "Cấu hình cấu trúc"

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

1

tạo một thư mục chính. như: 'res_notification_btn'

và tạo thư mục cây trong. như 'drawable' hoặc 'layout'

sau đó trong 'build.gradle' thêm cái này

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

Tất cả điều này là tự động hóa cách giải quyết được đề xuất bởi Cheezmeister. Nó làm việc cho tôi ... quan tâm để giải thích downvote?
Blake Miller


0

tài sản / Bạn có thể sử dụng nó để lưu trữ các tệp tài sản thô. Các tệp mà bạn lưu ở đây được biên dịch thành tệp .apk nguyên trạng và tên tệp gốc được giữ nguyên. Bạn có thể điều hướng thư mục này giống như một hệ thống tệp thông thường bằng cách sử dụng URI và đọc tệp dưới dạng luồng byte bằng AssetManager. Ví dụ, đây là một vị trí tốt cho kết cấu và dữ liệu trò chơi. http://developer.android.com/tools/projects/index.html


0

Các thư mục con không được phép, tài nguyên chỉ chứa [a-z0-9_.].

Không có bạn có chữ in hoa và không có dấu gạch chéo về phía trước.


-3
  1. Nhấp chuột phải vào Drawable
  2. Chọn Mới ---> Thư mục
  3. Nhập tên thư mục. Ví dụ: logo.png (vị trí sẽ hiển thị thư mục có thể vẽ theo mặc định)
  4. Sao chép và dán hình ảnh trực tiếp vào thư mục drawable. Trong khi dán, bạn có một tùy chọn để chọn mdpi / xhdpi / xxhdpi, v.v. cho mỗi hình ảnh từ danh sách. Chọn tùy chọn thích hợp và nhập tên của hình ảnh. Đảm bảo giữ cùng tên với tên thư mục tức là logo.png
  5. Làm tương tự cho các hình ảnh còn lại. Tất cả chúng sẽ được đặt dưới thư mục chính của logo.png.
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.