SyntaxHighlighter

2012/01/18

ImageViewを画面サイズに合わせて拡大させる



「ImageViewにdrawableを指定してfill_parentをしても、元の画像サイズが小さいと画面の両端まで拡大して表示してくれない!」ということはありませんか?

画像がスクリーンサイズギリギリに拡大されない問題にあたりましたので、対処法を調べてみました。これはそのメモです。

まずは現象の確認です。レイアウトXMLを次のように書いた場合で、

横方向にfill_parentを指定しているのですが、もし画像サイズが画面サイズよりも小さい場合、
と、このようにスクリーンサイズの横幅に応じてfill_parentしてくれていません。scaleTypeをfitXYに変更すると、横幅はいっぱいに広がりますが、縦横比を保持しながら縦幅を拡大してくれないため、横に間延びした画像になります。

これだと、
  • デバイスを縦横回転した場合
  • タブレットなどの高解像度デバイスでの実行を考慮した場合
などに、予期せぬレイアウト表示になる恐れがあります。

Androidにはdip指定で画面サイズを考慮した画像ファイルを用意してある程度差分をカバーすることができますが、どのくらい大きな解像度をもつ端末が今後出てくるかわかりません。

ひとつの解としては、とても大きな画像を用意して、実在するすべての端末で縮小表示をすることです。ただしこの場合は消費メモリやリソースサイズが大きくなることでしょう。

そこで今回は、ある程度の大きさの画像を用意しておくものの、予期せぬ高解像度デバイスの場合は拡大表示する術を考えてみました。

まずおそらく原因はImageViewがAndroidのスクリーンサイズを(当初)知ることができないことが原因かと思います。ImageViewは繰り返しチェックをしながらそのサイズを決めているらしく、その結果現在のような結果に陥っています。従って、スクリーンサイズを取得できるようになってから、改めてサイズを指定してあげれば正しくリサイズすることができそうです。

スクリーンサイズは、一旦描画した後に、ViewGroup#onSizeChanged()にて知ることができます。

はじめに、下記のクラスを用意してroot viewとして用いることで、スクリーンサイズを取得します。

onSizeChanged()にてスクリーンサイズを取得したら、元の画像をmatrixで拡大(縮小)します。matrixにより変換しているため、レイアウトxmlファイル中の


に変更します。

次に、ActivityのonCreate()にてHorizontallyExpandingImagesViewを設定します。
このようにすると、ActivityのonPause()の後に一旦描画が行われ、スクリーンサイズが確定したのち、HorizontallyExpandingImagesViewのonSizeChanged()にてImageViewの拡縮が行われます。

下記がその結果です。縦幅が拡大され、縦横比を維持しながらImageViewのサイズが画面サイズにフィットしているところがわかると思います。
分かりやすくするために、極度に小さい画像を用いたのでボケボケになっています。dipの設定で複数のdrawableを用意することで、極端な画像のクオリティの劣化は回避することができるでしょう。

1 件のコメント:

moririn-japan さんのコメント...

Matrixを新しくしないと縮小が重ねられてしまっていたので、
m.reset();
を追加しました。