Androidドローアブルディレクトリにサブディレクトリを含めることはできますか?


497

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ディレクトリでは大文字を使用できないことに注意してください。
タイラー

1
あなただけのGradleでこれを行うことができます: stackoverflow.com/a/19859379
Yair Kukielka

2
ドローアブル機能を使用して、ドローアブルにSIBLINGディレクトリを作成することは可能ですか?では、res / tanks / drawble- [hdpi .. etc]などですか。
Fattie、2014年

回答:


546

いいえ、リソースメカニズムは、ドローアブルディレクトリのサブフォルダーをサポートしていません。そのため、その階層をフラットに保つ必要があります。

表示されたディレクトリレイアウトでは、利用可能な画像はありません。

私自身の実験から、res/drawableフォルダ内にアイテムが含まれるサブフォルダがあると、リソースコンパイラが失敗し、R.javaファイルが正しく生成されないようです。


136
Android 2.2以降では、これはコンパイラエラーの原因にはなりませんが、Rクラスを生成するときにサブディレクトリは無視されます。これは本当にうんざりし、大きなプロジェクトの管理を難しくします。= /
Nik Reiman、2010

70
完全に同意する。彼らはサブフォルダをサポートするより良いソリューションを考え出す必要があります。それはそんなに難しいことではありません。
znq

13
うまくいけば、これはすぐに解決され、100以上のアセットがあり、それでもそれらの一部をコーディングしました。わずかに複雑なプロジェクトを管理しようとするトータルナイトマーレ。
エミール

14
これは、Android Issue Trackerの対応する問題です:code.google.com/p/android/issues/detail
id=

44
アンドロイドの呪い
ホイットニーランド

149

私が使用している回避策(およびAndroid自体が好むように見えるもの)は、基本的にスラッシュの代わりにアンダースコアを使用するため、構造は次のようになります。

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

このアプローチでは、ネーミングに細心の注意を払う必要があり、ファイル自体を複雑にするのはそれほど簡単ではありません(ドリンクとサンドイッチをすべて「food」にする必要があると判断した場合は、単に名前を変更するのではなく、大量の名前を変更する必要があります。それらをディレクトリに移動します); しかし、プログラミングロジックの複雑さは、同等のフォルダー構造と比較してそれほど悪くなりません。

この状況は確かに最悪です。Androidは、素晴らしい、ひどい設計上の決定が混在するバッグです。私たちは、後の部分がすべての当然の急ぎで取り除かれるのを望むことができるだけです:)


31
ドローアブルフォルダでは大文字は使用できないことに注意してください。「無効なファイル名:[a-z0-9_。]のみが含まれている必要があります」というエラーが表示される
Jason

5
「素晴らしい、ひどいデザイン決定の混合バッグ」の+1
ブレント・ファウスト14

1
回避策はほとんどありません。「完全に気が狂わないようにするためにすべきこと」ではありません。1つのディレクトリに限定するのは馬鹿げています。
RichieHH 14

35

実際、Android Studioでは可能です。次に示すように、リソースをネストできます

ここに画像の説明を入力してください

ここにリソースをグループ化するプラグインもあります


こんにちは、@ android開発者!これをbuild.gradleファイルに追加しようとしました:sourceSets {main {res {srcDir 'src / main / res / drawable / ic-toggle'}}} xmlnsの「Uriが登録されていません」 :android = " schemas.android.com/apk/res/android。何が
原因

@AlexKost私は実際にこれを一度だけ試しました。私はそれを助けるのに十分な経験がありません。ごめんなさい。
android開発者

@RahulMandaliya可能ではありますが、使用しないことをお勧めします。
Androidデベロッパー

@androiddeveloperなぜでしょうか?
Josh Hansen、

1
@JoshHansen汚いです。
Android開発者

34

はい-それは吸う:)しかし、あなたはassetsフォルダを使用してそこにサブディレクトリを持ち、そのように画像をロードすることができます。


6
問題は
ドローアブル

他の反対意見の場合、リソースは簡単にローカライズされる可能性がありますが、AFAIKにはアセット用の組み込みのメカニズムはありません。
Fran Marzoa

@anticafeはIDEで「リソースへ移動」を使用します(Eclipse:CTRL + SHIFT + R、IDEA / Android Studio:CTRL + SHIFT + N)
TWiStErRob '19

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のコメントに少なくとも1,000の賛成票を与える必要があります:)
HGPB

22

私は、ファイル名を2つのアンダースコアで区切って仮想サブフォルダーを作成できるEclipseプラグインを作成しました__。プロジェクトは初期段階ですが、IDEがクラッシュしないことを心配しないでください

詳細はここにあります。フォークしてプルリクエストを送信してください:

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

ここに画像の説明を入力してください


2
いいね!これをAndroid Studioに移植する可能性はありますか?
BVB 2014

1
私は現在androidスタジオも使用していないので、経験豊富な人が移植するのを待つ必要があると思います。
キリルクラコフ2014

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}のすべての「/」を「_」に置き換える必要があると思います。
Seunghoon

9

Gradleを備えたAndroid Studioでは、リソースを分離できる複数のソースディレクターを使用できます。例えば:

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

ただし、名前が衝突してはなりません。つまり、sandwiches_tunaOnRyeなどの名前が必要ですが、すべてのサンドイッチに個別のセクションを設定できます。

これにより、リソースをさまざまな構造で保存できます(actionbargeneratorなどの自動生成されたコンテンツに役立ちます)。


4

問題を部分的に回避する1つの方法は、APIレベルのサフィックスを使用することです。res / layout-v1、res / layout-v2などを使用して、同じAPKで複数のサブプロジェクトを保持しています。このメカニズムは、すべてのリソースタイプに使用できます。

明らかに、これはres / layout-vを超えるAPIレベルをターゲットにしている場合にのみ使用できますか?あなたが使用しています。

また、Android 1.5と1.6のバグにも注意してください。 APIレベルのサフィックスについては、Andoroidのドキュメントをご覧ください


この答えをダウングレードした人に:理由を説明できますか?このメカニズムは、きれいではありませんが、私にはうまく機能します。
OferR

4

ライブラリシステムの出現により、アセットの大きなセットごとにライブラリを作成することが解決策になる可能性があります。

すべてのアセットで同じ名前を使用しないようにする必要がありますが、ライブラリごとにプレフィックススキーマを使用すると問題が解決するため、問題が残ります。

フォルダを作成できるほど単純ではありませんが、それは物事を正気に保つのに役立ちます...


はい、いいと思います。私がdrawable-ldpiなどのフォルダに国旗を追加すると、それらがいっぱいになります。すべての汎用リソース用のライブラリプロジェクトを作成すると、積極的に取り組んでいるプロジェクトの混乱を減らすのに役立つと思います。驚いたのは賛成票が1つだけです。
トム

3

この状況には回避策があります。resVectorデフォルトのresフォルダーと同じレベルに(たとえば)フォルダーを作成できます。そこで、そこにdrawable-xxxリソースフォルダを追加できます。

resVector
-drawable
-layout
-color

その後、必要なのは追加することです

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

あなたのbuild.gradleファイルに(の中android { })。


悲しいことに、「Android」パースペクティブを使用すると、Android Studioのプロジェクトパネルでそれらがマージされます:(
AjahnCharles

@AjahnCharles-私はこの視点をまったく使用しないことを好みます(とにかく-私は常に「気晴らしフリーモード」で働いています)...しかし、あなたは正しいです-「Android」はすべてをマージします。
アントンDerevyanko

1

これは完璧な方法ではありません。ここに表示されるのと同じ方法を実装する必要があります

使用できるコードを使用して、フォルダーの下の画像を呼び出すこともできます

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

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

1

私のものではありませんが、この問題を探しているときにこのスレッドが見つかりました。AndroidStudioとGradleビルドシステムを使用している場合、プラグインは必要なく、ビルドファイルの編集はわずかです。

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


1

Android StudioでGradleを使用すると、このようにできます(リンク)。

「構造の構成」の段落にあります

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によって提案された回避策を自動化することです。それは私のために働いています...反対票を説明するのを気にしますか?
Blake Miller


0

assets /生のアセットファイルを保存するために使用できます。ここで保存したファイルは、そのまま.apkファイルにコンパイルされ、元のファイル名は保持されます。URIを使用して通常のファイルシステムと同じ方法でこのディレクトリをナビゲートし、AssetManagerを使用してバイトのストリームとしてファイルを読み取ることができます。たとえば、これはテクスチャやゲームデータに適した場所です。 http://developer.android.com/tools/projects/index.html


0

サブディレクトリは許可されていません。リソースには[a-z0-9_。]のみを含める必要があります。

大文字もスラッシュもありません。


-3
  1. ドローアブルを右クリック
  2. 新規--->ディレクトリを選択します
  3. ディレクトリ名を入力します。例:logo.png(デフォルトでは、この場所には既にドローアブルフォルダが表示されます)
  4. 画像をコピーして、ドローアブルフォルダーに直接貼り付けます。貼り付けている間、リストから画像ごとにmdpi / xhdpi / xxhdpiなどを選択するオプションが表示されます。適切なオプションを選択し、画像の名前を入力します。ディレクトリ名と同じ名前を必ず使用してください。つまり、logo.png
  5. 残りの画像についても同じようにします。それらはすべて、logo.pngメインフォルダーの下に配置されます。
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.