ひだまりソケットは壊れない

ソフトウェア開発に関する話を書きます。 最近は主に Android アプリ、Windows アプリ (UWP アプリ)、Java 関係です。

まじめなことを書くつもりでやっています。 適当なことは 「一角獣は夜に啼く」 に書いています。

Android アプリの Drawable リソースのエイリアスの作成について

当たり前の内容だけど日本語ドキュメントが間違っててバグを埋め込んでしまった (リリースはしてない) ので共有。

Drawable リソースのエイリアス作成

res/values/drawables.xml ファイルみたいなファイルを作って、そこに <drawable name="alias_name">@drawable/target_drawable</drawable> みたいなタグを書けばエイリアスを作れる。

To create an alias to an existing drawable, use the element. For example:

<?xml version="1.0" encoding="utf-8"?>
<resources>
  <drawable name="icon">@drawable/icon_ca</drawable>
</resources>

If you save this file as drawables.xml (in an alternative resource directory, such as res/values-en-rCA/), it is compiled into a resource that you can reference as R.drawable.icon, but is actually an alias for the R.drawable.icon_ca resource (which is saved in res/drawable/).

App resources overview  |  Android Developers

qualifiers との兼ね合い

以下のように、qualifiers 付きディレクトリにある実体のある Drawable リソースとエイリアスとで、ちゃんと切り替わることを確認。

  • res/drawable-v23/foo.xml というリソースファイル
  • res/values/drawables.xml<drawable name="foo">@drawable/target_drawable</drawable>

日本語ドキュメントが間違ってる件

日本語ドキュメントだと、

既存のドローアブルのエイリアスを作成するには、<bitmap> 要素を使用します。次に例を示します。

って書かれてる。 が、実際にこれをやって (Bitmap Drawable 以外の?) Drawable リソースのエイリアスを作成しようとすると実行時にエラーが発生する。 (API level 16、23、25 のエミュレータで確認。)

ドキュメントの誤りについては https://issuetracker.google.com/issues/78862550 に報告した。

`bitmap` 要素を使ったときのエラー例
<?xml version="1.0" encoding="utf-8"?>
<bitmap xmlns:android="http://schemas.android.com/apk/res/android"
    android:src="@drawable/simple_drawable" />

上のような XML ファイルを用意して、Drawable として読み込もうとすると以下のようなエラー。

    java.lang.RuntimeException: Unable to start activity ComponentInfo{info.vividcode.sample.simple/info.vividcode.sample.simple.MainActivity}: android.view.InflateException: Binary XML file line #31: Binary XML file line #31: Error inflating class ImageView
        at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2416)
        at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2476)
        (中略)
        at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616)
     Caused by: android.view.InflateException: Binary XML file line #31: Binary XML file line #31: Error inflating class ImageView
        at android.view.LayoutInflater.inflate(LayoutInflater.java:539)
        at android.view.LayoutInflater.inflate(LayoutInflater.java:423)
        (中略)
        at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726) 
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616) 
     Caused by: android.view.InflateException: Binary XML file line #31: Error inflating class ImageView
        at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:782)
        at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:704)
        (中略)
        at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726) 
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616) 
     Caused by: android.content.res.Resources$NotFoundException: File res/drawable/simple_drawable_3.xml from drawable resource ID #0x7f02005f
        at android.content.res.Resources.loadDrawableForCookie(Resources.java:2640)
        at android.content.res.Resources.loadDrawable(Resources.java:2540)
        at android.content.res.TypedArray.getDrawable(TypedArray.java:870)
        at android.widget.ImageView.<init>(ImageView.java:152)
        (中略)
        at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726) 
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616) 
     Caused by: org.xmlpull.v1.XmlPullParserException: Binary XML file line #2: <bitmap> requires a valid 'src' attribute
        (以下略)