【Android】背景画像のリピートが効かない問題

画像のコストを下げるために、背景画像に tileMode=”repeat” を指定してタイルとして使っていたのですが、
Android 2.3 系以下の端末で特定のアクティビティでだけリピートが聞かなくてハマりました。

どうやらハニカムで修正されたOSの不具合だそうで…以下対策がわかったのでメモ。

どういう状況?

タイル背景(bg.xml)はこんな感じです。

<!-- res/drawable/bg.xml -->
< ?xml version="1.0" encoding="utf-8"?>
<bitmap xmlns:android="http://schemas.android.com/apk/res/android"
    android:antialias="true"
    android:dither="false"
    android:filter="false"
    android:gravity="fill"
    android:src="@drawable/bg_repeat"
    android:tileMode="repeat"></bitmap>

これを各レイアウトで次のように使っています。

< ?xml version="1.0" encoding="utf-8"?>
<relativelayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@drawable/bg" >

リピートが効く画面もあるのですが、効かない画面では伸びたタイル画像が
1枚だけ表示されてしまいます。これはかっこ悪い。

直し方は?

StackOverFlow(background image not repeating in android layout)に書かれていました。

下のコードを適宜、描画の更新タイミングでリピートを行なっているビューに対して実行するといいようです。

public static void fixBackgroundRepeat(View view) {
      Drawable bg = view.getBackground();
      if(bg != null) {
           if(bg instanceof BitmapDrawable) {
                BitmapDrawable bmp = (BitmapDrawable) bg;
                bmp.mutate(); // make sure that we aren't sharing state anymore
                bmp.setTileModeXY(TileMode.REPEAT, TileMode.REPEAT);
           }
      }
 }

画面背景のリピートを修正するならこのように実行すればいいでしょう。

fixBackgroundRepeat(this.findViewById(android.R.id.content)
				.getRootView());

どうしてこうなった

StackOverFlowのコメントによると、ハニカム(Android 3.0)で修正された不具合のようで、同じ画面でBitmapDrawableが多数使われていると、内部でのBitmap(とBitmapの状態設定)の再利用のタイミングでtileMode設定が簡単に失われてしまうようです。

対策で行っていることは、消えてしまった背景画像のリピート設定を再度設定し直しているのですね。