View
クラスのforceLayout()
、requestLayout()
、およびinvalidate()
メソッドの役割について少し混乱しています。
彼らはいつ呼ばれますか?
FrançoisBOURLIEUX および Dalvik によって提供される回答をよりよく理解するには、この素晴らしいビューライフサイクル図を Arpit Mathur でご覧になることをお勧めします。
invalidate()
ビューの再描画をスケジュールする場合は、invalidate()
を呼び出します。最終的にonDraw
が呼び出されます(すぐにではなく、すぐに)。カスタムビューが呼び出すタイミングの例は、テキストまたは背景色のプロパティが変更されたときです。
ビューは再描画されますが、サイズは変更されません。
requestLayout()
ビューに関する変更がサイズに影響する場合は、requestLayout()
を呼び出す必要があります。これにより、onMeasure
とonLayout
が、このビューだけでなく、親ビューのすべての行でトリガーされます。
requestLayout()
の呼び出しは 結果がonDraw
になるとは限りません (受け入れられた答えの図が示すものとは反対)であるため、通常はinvalidate()
と組み合わされます。
invalidate();
requestLayout();
この例は、カスタムラベルのテキストプロパティが変更された場合です。ラベルのサイズが変わるため、再測定して再描画する必要があります。
forceLayout()
親ビューグループで呼び出されるrequestLayout()
がある場合、その子ビューを再測定して再レイアウトする必要はありません。ただし、子を再測定と再レイアウトに含める必要がある場合は、子に対してforceLayout()
を呼び出すことができます。 forceLayout()
は、直接の親でrequestLayout()
と一緒に発生した場合にのみ、子で機能します。 forceLayout()
を単独で呼び出しても、ビューツリーでrequestLayout()
をトリガーしないため、効果はありません。
forceLayout()
の詳細については、 このQ&A を参照してください。
View
ソースコードここでいくつかの応答を見つけることができます: http://developer.Android.com/guide/topics/ui/how-Android-draws.html
私にとっては、invalidate()
への呼び出しはビューのみを更新し、requestLayout()
への呼び出しはビューを更新し、画面上のビューのサイズを計算します。
再描画するビューでinvalidate()を使用すると、onDraw(Canvas c)が呼び出され、requestLayout()によってレイアウトレンダリング全体(測定フェーズと位置決めフェーズ)が再度実行されます。実行時に子ビューのサイズを変更する場合に使用する必要がありますが、親ビューからの制約のような特定の場合にのみ使用します(つまり、親の高さまたは幅はWRAP_CONTENTであるため、再度ラップする前に子を測定します)
この回答 はforceLayout()
について正しくありません。
forceLayout()
のコード でわかるように、ビューに「再レイアウトが必要」とマークするだけですが、再レイアウトをスケジュールもトリガーもしません。将来のある時点で、ビューの親が他の何らかの理由でレイアウトされるまで、再レイアウトは発生しません。
forceLayout()
およびrequestLayout()
を使用する場合には、さらに大きな問題もあります。
ビューでforceLayout()
を呼び出したとしましょう。そのビューの子孫でrequestLayout()
を呼び出すと、Androidはその子孫の祖先でrequestLayout()
を再帰的に呼び出します。問題は、forceLayout()
を呼び出したビューで再帰が停止することです。 したがって、requestLayout()
呼び出しはビュールートに到達しないため、レイアウトパスをスケジュールすることはありません。ビュー階層のサブツリー全体がレイアウトを待って呼び出していますそのサブツリーのどのビューでもrequestLayout()
はレイアウトを引き起こしません。そのサブツリーの外側のビューでrequestLayout()
を呼び出すだけで、スペルが壊れます。
forceLayout()
の実装(およびそれがrequestLayout()
にどのように影響するかを破壊することを検討します。コードでその関数を使用しないでください。