フォーカスを取得した Activity
は、レイアウトを描画するようリクエストされます。描画の手順は Android フレームワークによって処理されますが、レイアウト階層のルートノードは Activity
で指定する必要があります。
描画は、レイアウトのルートノードから始まります。続いて、レイアウト ツリーの測定と描画がリクエストされます。描画の処理では、ツリーをたどって無効な領域と交差する各 View
がレンダリングされます。その過程で、各 ViewGroup
はすべての子に対して(draw()
メソッドで)描画をリクエストする役割を担い、また各 View
は自身の描画を行う役割を担います。ツリーは前順で走査されるため、親は子より前(つまり背後)に描画され、兄弟はツリーに表示された順序で描画されます。
注: フレームワークでは、有効な領域にない View
オブジェクトは描画されません。なお、View
背景の描画も処理されます。
View
を強制的に描画させるには、invalidate()
を呼び出します。
レイアウトの描画は、測定パスとレイアウトパスの 2 つのパスからなるプロセスです。
測定パス
測定パスは measure(int, int)
で実装されます。走査は View
ツリーの上から下に向かって行われます。この繰り返しの間に、各 View
により寸法指定がツリーの下方にプッシュされます。測定パスの終了時には、すべての View
に測定値が保存されています。2 番目のパスは layout(int, int, int, int)
で実装されます。この走査も上から下に向かって行われます。このパスでは、各親は、測定パスで計算されたサイズを使用して、すべての子を配置する役割を担います。
View
オブジェクトの measure()
メソッドが返された時点では、その View
オブジェクトのすべての子孫も含め、getMeasuredWidth()
と getMeasuredHeight()
の値が設定されているはずです。View
オブジェクトの幅と高さの測定値は、その View
オブジェクトの親から課された制約に従う必要があります。これにより、測定パスの最後には、すべての親がすべての子の測定値を受け入れることが保証されます。親 View
は、子に対して measure()
を複数回呼び出すことがあります。たとえば、親はまず寸法を指定せずに子の測定を行い、それぞれがどのくらいの大きさになるかを確認します。そして、制約をかけないと子のサイズの合計が大きすぎる、または小さすぎる場合は、再度 measure()
を呼び出して実際の数を指定します(つまり、子同士でそれぞれの獲得スペースについての折り合いがつかない場合は、親が介入して 2 回目のパスでルールを設定するということです)。
測定パスでは、寸法の伝達に 2 つのクラスが使用されます。ViewGroup.LayoutParams
クラスは、View
オブジェクトによって、希望する測定値と配置を親に通知するために使用されます。つまり、ベースの ViewGroup.LayoutParams
クラスには、View
の幅と高さの両方について、希望値が記述されているにすぎません。このクラスには、各寸法に次のいずれかを指定できます。
- 特定値。
MATCH_PARENT
。View
が親(からパディングを差し引いた領域)と同じ大きさになるという意味。WRAP_CONTENT
。View
がコンテンツ(にパディングを加えた領域)を囲める大きさになるという意味。
ViewGroup
のさまざまなサブクラスに、ViewGroup.LayoutParams
サブクラスがあります。たとえば、RelativeLayout
には固有の ViewGroup.LayoutParams
サブクラスがあり、これには子 View
オブジェクトを水平および垂直方向に中央揃えする機能が含まれています。
MeasureSpec
オブジェクトは、要件を親から子に向けて、ツリー下方にプッシュするために使用されます。MeasureSpec
のモードは、次の 3 つのうちのいずれかになります。
UNSPECIFIED
: これは、親が子View
の適切な寸法を判断するために使用します。たとえばLinearLayout
では、子に対して高さをUNSPECIFIED
、幅をEXACTLY
240 に指定してmeasure()
を呼び出すことにより、子View
の幅が 240 ピクセルだと高さはどの程度になるのかを調べることができます。EXACTLY
: これは、親が子のサイズを特定値で指定するために使用します。子は指定されたサイズを使用する必要があり、さらに子孫がすべてこのサイズに収まることを保証しなければなりません。AT MOST
: これは、親が子の最大サイズを指定するために使用します。子は、自身と子孫がすべてこのサイズに収まることを保証しなければなりません。
レイアウトパス
レイアウトを開始するには、requestLayout()
を呼び出します。このメソッドは通常、View
によって、それ自身が現在の範囲に収まらないと判断された場合に呼び出されます。