スポンサーサイト

上記の広告は1ヶ月以上更新のないブログに表示されています。
新しい記事を書く事で広告が消せます。

[Android]ImageViewの表示サイズの決まり方

ImageViewのビュー自体のサイズと、中身(Drawable)の表示のされ方はいろいろな要素に影響されて決まる。
ちょっとわかりにくいのでざっと整理してみたいと思う。

(この記事を読むには、Androidのレイアウト計算についてなどで、レイアウトの決まり方を知っておく必要あり)

サイズに影響を与える要素は以下の10個がある。

  1. 親ViewGroupからのmeasureSpec
  2. DrawableのIntrinsicWidth/Height(Bitmapなどの大きさ)
  3. minWidth/Height
  4. maxWidth/Height
  5. BackgroundDrawableのIntrinsicWidth/Height
  6. adjustViewBounds
  7. padding
  8. matrix
  9. scaleType
  10. cropToPadding

このうち、ビューのサイズに影響を与えるのは1~7のみで、8~10はDrawableの表示のみに影響を与える。

ImageViewのソースから、Drawableをセットした場合の処理の流れを追いかけてみる。
setImageURI/setImageResource/setImageDrawableなどDrawableを変更するメソッドを呼ぶと、最後にrequestLayoutが呼ばれる。
requestLayoutを呼び出すと、フレームワークからmeasureが呼ばれ、measureの中からonMeasureが呼ばれる。ここでViewのWidth/Heightが決まる。
Width/Heightが決まるとフレームワークからlayoutが呼ばれ、layoutの中からsetLayoutが呼ばれる。setLayoutはさらにconfigureBounds(private関数)を呼び出す。ここで、Drawableの表示方法が決められる。

onMeasure


onMeasureの中では、以下のような方法で幅・高さが決められている(ただし、説明を簡単にするためにpaddingは0と仮定)
・adjustViewBoundsがtrueで、measureSpecの指定が幅・高さのどちらかが可変の場合
 DrawableのIntrinsicWidth/Heightを、measureSpecとmaxで調整して幅・高さを仮ぎめする(ここで最大が決まる)
 幅・高さをDrawableのアスペクト比と同じになるように調整する。
 順序は、幅→高さの順。仮ぎめしたものより小さくなる。
 調整が効かなかった場合は、仮ぎめしたものがそのまま使われる。
 
・上記以外の場合
 DrawableのIntrinsicWidth/Heightを、
 ・measureSpec/EXACTLY
 ・min以上 && BackgroundDrawableのIntrinsicWidth/Height以上
 ・max以下 && measureSpec/AT_MOST 以下
 の制約条件を満たすように調整する(優先度は上から順)
 
(注)adjustViewBounds=trueの場合、minは無視されることになる

configureBounds


configureBoundsでは、DrawableのIntrinsicWidth/HeightとViewのWidth/Heightが所与のものとして、ScaleTypeを元にDrawableを描画する時のMatrixを計算する。
(レイアウトが完了していない場合にも呼ばれることもあるが、その場合は何もしない)

・fitXY
 Viewのwidth,heightになるようにMatrixを設定
・matrix
 setImageMatrixで指定したMatrixをそのまま使う
・center
 Drawableを中央に配置するようにMatrixを設定
・center_crop
 Drawableを、アスペクト比を維持しつつ隙間がなくなるように拡大・縮小して中央に配置するようにMatrixを設定
・center_inside
 Drawableを、アスペクト比を維持しつつ全てが収まるように拡大・縮小して配置するようにMatrixを設定
・fitStart, fitEnd, fitCenter
 Matrix#ScaleToFitにおまかせ

onDraw


onDrawで計算したMatrixを使って描画を行う。
ただし、ViewよりDrawableのほうが大きい場合、CropToPaddingでpaddingの処理が変わる。
具体的には、CropToPaddingがfalse(デフォルト)の場合は、はみ出した箇所にはpaddingが表示されない(paddingの領域にもDrawableが描画される)が、trueだと常にpaddingが表示される。




スポンサーサイト

コメント

非公開コメント

プロフィール

fchiba

Author:fchiba
FC2ブログへようこそ!

最新記事
最新コメント
最新トラックバック
月別アーカイブ
カテゴリ
検索フォーム
RSSリンクの表示
リンク
ブロとも申請フォーム

この人とブロともになる

QRコード
QRコード
上記広告は1ヶ月以上更新のないブログに表示されています。新しい記事を書くことで広告を消せます。