はじめに
普段は、iosエンジニアなのですが、androidも書きたくて、まず参考書を読むことにしました。
Androidはなんとなく全体像は知っているので、一番気になるレイアウトの章から読みました。
全部読み終えてから、改めてまとめるつもりなので、
この記事では、その時用のメモのようにラフにまとめます。
ビューのヒエラルキー
ViewGroupeだけがサブビューを持てる。
iosではどのviewもsubviewsプロパティにサブビューを格納できるので、汎用性はiosの方が高いか。
レイアウト
仕事としてはmeasureパスとlayoutパスがあり、
measureパスはサイズ、layoutパスは座標を決定する。
measureパスが終わってから、layoutパスがよばれる。
つまり、ビューヒエラルキー内のビューのサイズを全て決定してから、適当な座標に置いていく感じか。
measure()
Viewクラスにはmeasure()メソッドがあり、自身のサイズをこの中で決定する。
measure()
メソッド内で、onMeasure(int widthMeasureSpec, int heightMeasureSpec)
がよばれ、さらにその内部でsetMeasuredDimension(int measuredWidth, int measuredHeight)
がよばれる。
こんな感じ
measure()
> onMeasure()
> setMeasuredDimension()
後の2つのメソッドの役割は、
onMeasure(int widthMeasureSpec, int heightMeasureSpec)
:
引数に親ビューからのサイズ制約を受け取り、自身のサイズを決定する。
setMeasuredDimension(int measuredWidth, int measuredHeight)
:
自身のサイズを引数に受け取って申告する。
layout三態
onMeasure(int widthMeasureSpec, int heightMeasureSpec)
の引数で受け取る値には、制約パラメータが入っていてこんな感じ。
EXACTLY: 親ビュー値は数値のハードコード。(このビューではこの親ビュー数値以内でメジャーしないと見切れる)
AT_MOST: 最大でもこの値以下でメジャーしてね。
UNEXPECTED: どんな値でもいいよ。(親ビューがwrap_contentとか。)
ViewGroupのmeasure()
onMeasure()内で、
まず子ビューのmesure()を全て呼び出し、全ての子ビューのサイズを確定させる。その後、子ビューのサイズと自身の設定をもとに、setMeasuredDimension()で自身のサイズをで申告する。
子ビューのonMeasure()では、ViewGroup自身の制約とViewGroupがonMeasure(int widthMeasureSpec, int heightMeasureSpec)で親から受け取った値をいい感じに合わせて、受け取っている。
ViewGroupでないViewのmeasure()
onMeasure()の引数と自身の設定(wrap_contentなど)を基に、setMeasuredDimension()でサイズを申告する。
必ず末端のviewなので、子ビューを考慮する必要なし。
layout()
サイズの決まったviewを親ビューから良き座標に置いていく。
特にいうことなし。
参考文献