9パッチリソースの複雑さ

このメモでは、Androidで「伸縮可能な」グラフィックデザイン要素を作成するために使用される9パッチ構造の非自明な機能について説明します。





このテーマに関する記事は既にあるので、私はそれが何であるかについては触れません。 ストレッチ画像を作成するための重要な要素は、いわゆるチャンク、バイト[]のような構造です。 このチャンクはNinePatchコンストラクターで使用されますが、それが何であるかに関するドキュメントはあまり冗長ではありません。



public NinePatch (Bitmap bitmap, byte[] chunk, String srcName)

chunk The 9-patch data chunk describing how the underlying bitmap is split apart and drawn.



Bitmap.getNinePatchChunk()

Returns an optional array of private data, used by the UI system for some bitmaps. Not intended to be called by applications.









チャンクはどこから来たのですか?

9パッチリソースは、2つのタイプのいずれかに存在できます。 1つ目は、ストレッチ領域を指定する黒い単一ピクセルのラインマーカーを使用した同じ画像です。 2番目のタイプがコンパイルされます。 外部でコンパイルされた画像は元の画像とまったく同じに見えますが、マーカーラインは視覚的には表示されず、バイナリ形式に変換され、コード名「npTc」の下に縫い付けられます。 最初のタイプから2番目のタイプへの変換は、リソースを準備する段階で、aaptユーティリティによって実行されます。



明確にするために、1つの赤いピクセルで構成される写真を撮り、適切なユーティリティを使用して9パッチのリソースにします。 16進エディタでコンパイル済みバージョンと比較します。



元の画像の9ピクセル(1 + 8ピクセルマーカー)

画像



npTcラベルの後の1ピクセル+バイナリデータ

画像



これらのフォームにはそれぞれ長所と短所があります。一方で、コンパイルされたフォームはランタイムでの使用に最適化されていますが、グラフィカルエディタで変更することはできません。再保存すると、チャンクは必ず上書きされます。



この構造の正確な内容とその内容は、 ソースで読み取ることができます (構造Res_png_9patchを参照)



なぜこれを知る必要があるのですか?

9パッチリソースのドキュメントには、「拡張子.9.pngで保存し、プロジェクトのres / drawable /ディレクトリに保存する必要があります」と記載されています。 したがって、これはaaptがリソースをコンパイルする唯一の場所です。 しかし、別の場所、たとえば、アセットフォルダーから写真を撮りたい場合や、実行時にダウンロードしたい場合はどうでしょうか? これを試してみましょう:



public NinePatchDrawable create9Patch() {

Bitmap raw = BitmapFactory.decodeStream(...);

byte [] chunk = raw.getNinePatchChunk();

NinePatch patch = new NinePatch(raw, chunk, null );

return new NinePatchDrawable(patch);

}




* This source code was highlighted with Source Code Highlighter .






この方法で未加工のリソースから直接NinePatchを作成しようとすると、仮想マシンの野生のどこか、特にraw.getNin​​ePatchChunk()行にネイティブキャッシュが作成されます。これは非常に論理的です。マーカー。



I/DEBUG ( 4694): signal 11 (SIGSEGV), fault addr 00000008

I/DEBUG ( 4694): r0 0000bd00 r1 00000007 r2 ad03db59 r3 00000000

I/DEBUG ( 4694): r4 0000bd00 r5 00000000 r6 ad3431b1 r7 41049cf8

I/DEBUG ( 4694): r8 beb484b8 r9 41049cf0 10 41049ce0 fp 00000000

I/DEBUG ( 4694): ip ad3431b1 sp beb48498 lr ad046f05 pc ad03db6c cpsr 00000030

I/DEBUG ( 4694): #00 pc 0003db6c /system/lib/libdvm.so

I/DEBUG ( 4694): #01 pc 000431c6 /system/lib/libandroid_runtime.so

I/DEBUG ( 4694): #02 pc 0000e434 /system/lib/libdvm.so

I/DEBUG ( 4694): #03 pc 00040b0a /system/lib/libdvm.so

I/DEBUG ( 4694): #04 pc 00013198 /system/lib/libdvm.so

I/DEBUG ( 4694): #05 pc 00017b9c /system/lib/libdvm.so

...









解決策は、すでにコンパイルされたリソースをシステムにパームアウトすることです。 これを行う最も簡単な方法は次のとおりです:空のAndroidプロジェクトを取得し、リソースをres / drawableに配置し、コンパイルし、apkをエクスポートし、アーカイブとしてapkを開き、同じ場所から同じリソースを引き出しますが、すでにコンパイルされています。 それらをアプリケーション(または他の場所)のアセットにコピーし、上記のコードを使用してビットマップから有効なNinePathオブジェクトを構築できます。



そのようなこと。



All Articles