web-dev-qa-db-ja.com

forceLayout()、requestLayout()およびinvalidate()の使用

ViewクラスのforceLayout()requestLayout()、およびinvalidate()メソッドの役割について少し混乱しています。

彼らはいつ呼ばれますか?

155
fiddler

FrançoisBOURLIEUX および Dalvik によって提供される回答をよりよく理解するには、この素晴らしいビューライフサイクル図を Arpit Mathur でご覧になることをお勧めします。 enter image description here

314
Bartek Lipinski

invalidate()

ビューの再描画をスケジュールする場合は、invalidate()を呼び出します。最終的にonDrawが呼び出されます(すぐにではなく、すぐに)。カスタムビューが呼び出すタイミングの例は、テキストまたは背景色のプロパティが変更されたときです。

ビューは再描画されますが、サイズは変更されません。

requestLayout()

ビューに関する変更がサイズに影響する場合は、requestLayout()を呼び出す必要があります。これにより、onMeasureonLayoutが、このビューだけでなく、親ビューのすべての行でトリガーされます。

requestLayout()の呼び出しは 結果がonDrawになるとは限りません (受け入れられた答えの図が示すものとは反対)であるため、通常はinvalidate()と組み合わされます。

invalidate();
requestLayout();

この例は、カスタムラベルのテキストプロパティが変更された場合です。ラベルのサイズが変わるため、再測定して再描画する必要があります。

forceLayout()

親ビューグループで呼び出されるrequestLayout()がある場合、その子ビューを再測定して再レイアウトする必要はありません。ただし、子を再測定と再レイアウトに含める必要がある場合は、子に対してforceLayout()を呼び出すことができます。 forceLayout()は、直接の親でrequestLayout()と一緒に発生した場合にのみ、子で機能します。 forceLayout()を単独で呼び出しても、ビューツリーでrequestLayout()をトリガーしないため、効果はありません。

forceLayout()の詳細については、 このQ&A を参照してください。

さらなる研究

101
Suragch

ここでいくつかの応答を見つけることができます: http://developer.Android.com/guide/topics/ui/how-Android-draws.html

私にとっては、invalidate()への呼び出しはビューのみを更新し、requestLayout()への呼び出しはビューを更新し、画面上のビューのサイズを計算します。

25

再描画するビューでinvalidate()を使用すると、onDraw(Canvas c)が呼び出され、requestLayout()によってレイアウトレンダリング全体(測定フェーズと位置決めフェーズ)が再度実行されます。実行時に子ビューのサイズを変更する場合に使用する必要がありますが、親ビューからの制約のような特定の場合にのみ使用します(つまり、親の高さまたは幅はWRAP_CONTENTであるため、再度ラップする前に子を測定します)

3
Nativ

この回答forceLayout()について正しくありません。

forceLayout()のコード でわかるように、ビューに「再レイアウトが必要」とマークするだけですが、再レイアウトをスケジュールもトリガーもしません。将来のある時点で、ビューの親が他の何らかの理由でレイアウトされるまで、再レイアウトは発生しません。

forceLayout()およびrequestLayout()を使用する場合には、さらに大きな問題もあります。

ビューでforceLayout()を呼び出したとしましょう。そのビューの子孫でrequestLayout()を呼び出すと、Androidはその子孫の祖先でrequestLayout()を再帰的に呼び出します。問題は、forceLayout()を呼び出したビューで再帰が停止することです。 したがって、requestLayout()呼び出しはビュールートに到達しないため、レイアウトパスをスケジュールすることはありません。ビュー階層のサブツリー全体がレイアウトを待って呼び出していますそのサブツリーのどのビューでもrequestLayout()はレイアウトを引き起こしません。そのサブツリーの外側のビューでrequestLayout()を呼び出すだけで、スペルが壊れます。

forceLayout()の実装(およびそれがrequestLayout()にどのように影響するかを破壊することを検討します。コードでその関数を使用しないでください。

3
fluidsonic