web-dev-qa-db-ja.com

無効化の直後にrequestLayoutが呼び出されるのはなぜですか

私はカスタムビューについて学び、invalidate()requestLayout()について学びたいと思っていました。

この回答とその図を参照してください。

https://stackoverflow.com/a/25846243/4243687

invalidate()は、ビューの状態が変更され、再描画する必要があることをAndroidに通知します。

requestLayout()は、ビューのサイズが変更された可能性があり、再測定してから再描画する必要があることを意味します。

invalidate()dispatchDraw()draw()、およびonDraw()を呼び出すため、ビューを再レンダリングします。

一方、requestLayout()は、測定から再レンダリングまで、ほとんどすべてを実行します。

なぜそこにある多くの例(TextViewソースコードでさえ)が次の行でinvalidate()を呼び出し、次にrequestLayout()を呼び出すのですか?

13
Ersen Osman

invalidate()は、ビューのコンテンツを再描画するために特に使用されます。再描画は同期的に行われません。代わりに、ビューの領域に無効のフラグを付けて、次のレンダリングサイクル中に再描画されるようにします。

requestLayout()は、その中の何かがその寸法を変更した可能性がある場合に使用する必要があります。この場合、親ビューとビュー階層の上位にある他のすべての親は、レイアウトパスを介して自分自身を再調整する必要があります。

ビューのサイズを変更するようなことを何もしていない場合は、requestLayout()を呼び出す必要はありません。

戻って、requestLayout()が呼び出されているTextViewのコード内の場所を見ると、ビューの境界が影響を受けるメソッド上にあります。たとえば、setPadding()setTypeface()setCompoundDrawables()などです。

したがって、requestLayout()を呼び出すときは、ビュー全体が確実に再描画されるように、invalidateの呼び出しと組み合わせる必要があります。

11
Michael Krause

次の図 を見た後、requestLayout()を呼び出すと最終的にonDrawになるという印象を受けました。

enter image description here

したがって、冗長になるため、これらを一緒に呼び出す必要はありません。

_invalidate();
requestLayout();
_

ただし、その図は誤解を招く可能性があります。一部のビューは、レイアウトが変更されると実際に無効になる場合がありますが、これは確実ではありません。 requestLayout()を呼び出すと、onDrawが呼び出されるとは限りません。

私の ソース (ありがとう このコメント )は Romain Guy (GoogleのエンジニアAndroid )::

requestLayout()自体は描画パスにつながりませんが、一部のビューは、invalidateを呼び出すことによってレイアウトの変更に反応する場合があります。

したがって、リレーアウトによって再描画が行われることを確認するには、invalidate()requestLayout()をペアにする必要があります。 (ただし、逆は当てはまりません。再描画のみが必要な場合は、requestLayout()を呼び出す必要はありません。単一のinvalidate()で十分です。)

9
Suragch

本からの関連する抜粋 エキスパートAndroid それは質問に答えます:

OnClickイベントによってサイズが変更されたため、ビューを大きくしてスペースをとる必要があります。その必要性をAndroidにどのように表現しますか?そうですね、Layout()をリクエストします。このメソッドはチェーンを上って行き、すべてのビューの親に再測定が必要であることを示します。最後の親がこの要求(ビュールート)を取得すると、親はレイアウトトラバーサルをスケジュールします。レイアウトトラバーサルはonDrawになる場合とならない場合がありますが、この場合はそうなるはずです。優れたプログラミング手法として、invalidate()を呼び出して、描画フェーズも確実にします。

2
a-hegde

Androidドキュメント:ビュークラスの作成

public boolean isShowText() {
   return mShowText;
}

public void setShowText(boolean showText) {
   mShowText = showText;
   invalidate();
   requestLayout();
}

SetShowTextがinvalidate()とrequestLayout()を呼び出すことに注意してください。これらの呼び出しは、ビューが確実に動作することを保証するために重要です。外観を変更する可能性のあるプロパティを変更した後は、ビューを無効にして、システムが再描画する必要があることを認識できるようにする必要があります。同様に、ビューのサイズや形状に影響を与える可能性のあるプロパティが変更された場合は、新しいレイアウトをリクエストする必要があります。これらのメソッド呼び出しを忘れると、見つけにくいバグが発生する可能性があります。

0
Sotti