onMeasureカスタムビューの説明 質問する

onMeasureカスタムビューの説明 質問する

カスタム コンポーネントを作成しようとしました。クラスを拡張し、オーバーライドされたメソッドViewで描画を行います。オーバーライドする必要があるのはなぜですか? オーバーライドしなければ、すべてが正しいように見えます。誰か説明してもらえますか?メソッドをどのように記述すればよいですか? いくつかのチュートリアルを見ましたが、それぞれが少しずつ異なります。最後に呼び出す場合もあれば、使用して呼び出さない場合もあります。違いはどこにあるのでしょうか?onDrawonMeasureonMeasuresuper.onMeasuresetMeasuredDimension

結局、まったく同じコンポーネントをいくつか使用したいのです。それらのコンポーネントをファイルに追加しました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() Viewsuper

確かに、フレームワークはデフォルトの実装を適用するため、このメソッドをオーバーライドする必要はないかもしれませんが、オーバーライドしないと、ビューのスペースがコンテンツよりも小さい場合にクリッピングが発生する可能性があります。また、カスタム ビューを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);
}

おすすめ記事