カスタム コンポーネントを作成しようとしました。クラスを拡張し、オーバーライドされたメソッドView
で描画を行います。オーバーライドする必要があるのはなぜですか? オーバーライドしなければ、すべてが正しいように見えます。誰か説明してもらえますか?メソッドをどのように記述すればよいですか? いくつかのチュートリアルを見ましたが、それぞれが少しずつ異なります。最後に呼び出す場合もあれば、使用して呼び出さない場合もあります。違いはどこにあるのでしょうか?onDraw
onMeasure
onMeasure
super.onMeasure
setMeasuredDimension
結局、まったく同じコンポーネントをいくつか使用したいのです。それらのコンポーネントをファイルに追加しましたXML
が、どれくらいの大きさにすればよいかわかりません。後で、カスタム コンポーネント クラスで位置とサイズを設定したいと思います (描画時にサイズを設定する必要があるonMeasure
のはなぜですかonDraw
。動作も正常です)。いつそれを実行する必要がありますか?
ベストアンサー1
onMeasure()
これは、親によって提供されるレイアウト制約に応じて、カスタム ビューをどの程度の大きさにするかを Android に伝える機会です。また、カスタム ビューがそれらのレイアウト制約を学習する機会でもあります (match_parent
状況によって異なる動作をしたい場合wrap_content
)。これらの制約は、メソッドに渡される値にパッケージ化されていますMeasureSpec
。モード値の大まかな相関関係は次のとおりです。
- EXACTLY は、
layout_width
または値が特定の値に設定されたことを意味しますlayout_height
。おそらく、ビューをこのサイズにする必要があります。match_parent
が使用されるときにも、サイズを親ビューに正確に設定するためにこれがトリガーされる可能性があります (これはフレームワークのレイアウトに依存します)。 - AT_MOST は通常、
layout_width
またはlayout_height
値が設定されているmatch_parent
か、wrap_content
最大サイズが必要な場所 (これはフレームワークのレイアウトに依存します) であり、親ディメンションのサイズが値であることを意味します。このサイズよりも大きくしないでください。 - UNSPECIFIED は通常、
layout_width
またはlayout_height
値が制限なしで設定されたことを意味しwrap_content
ます。任意のサイズにすることができます。一部のレイアウトでは、このコールバックを使用して、2 番目の測定要求で実際に再度渡す仕様を決定する前に、必要なサイズを判断します。
に存在する規約は、ビューにしたいサイズを指定して を最後に呼び出す必要があるonMeasure()
ということです。このメソッドは、 にあるデフォルトの実装を含むすべてのフレームワーク実装によって呼び出されるため、ユースケースに適合する場合は代わりにを呼び出しても安全です。setMeasuredDimension()
View
super
確かに、フレームワークはデフォルトの実装を適用するため、このメソッドをオーバーライドする必要はないかもしれませんが、オーバーライドしないと、ビューのスペースがコンテンツよりも小さい場合にクリッピングが発生する可能性があります。また、カスタム ビューをwrap_content
両方向にレイアウトすると、フレームワークがビューの大きさを認識しないため、ビューがまったく表示されない可能性があります。
一般的に、別の既存のウィジェットではなくオーバーライドする場合はView
、次のような単純なものであっても、実装を提供することをお勧めします。
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int desiredWidth = 100;
int desiredHeight = 100;
int widthMode = MeasureSpec.getMode(widthMeasureSpec);
int widthSize = MeasureSpec.getSize(widthMeasureSpec);
int heightMode = MeasureSpec.getMode(heightMeasureSpec);
int heightSize = MeasureSpec.getSize(heightMeasureSpec);
int width;
int height;
//Measure Width
if (widthMode == MeasureSpec.EXACTLY) {
//Must be this size
width = widthSize;
} else if (widthMode == MeasureSpec.AT_MOST) {
//Can't be bigger than...
width = Math.min(desiredWidth, widthSize);
} else {
//Be whatever you want
width = desiredWidth;
}
//Measure Height
if (heightMode == MeasureSpec.EXACTLY) {
//Must be this size
height = heightSize;
} else if (heightMode == MeasureSpec.AT_MOST) {
//Can't be bigger than...
height = Math.min(desiredHeight, heightSize);
} else {
//Be whatever you want
height = desiredHeight;
}
//MUST CALL THIS
setMeasuredDimension(width, height);
}