1. ホーム
  2. android

[解決済み] onMeasure カスタムビューの説明

2022-03-17 20:01:01

質問

カスタムコンポーネントを作ろうとしました。私は View クラスで、いくつかの描画を onDraw をオーバーライドしたメソッドです。なぜオーバーライドする必要があるかというと onMeasure ? そうでなければ、すべてが正しく見えるのですが。どなたか説明してください。どのように私は私の onMeasure メソッドを使うことができますか?いくつかのチュートリアルを見たのですが、それぞれ少し違っています。時々、彼らは super.onMeasure を使うこともあれば setMeasuredDimension と呼び出さなかった。その違いはどこにあるのでしょうか?

結局、全く同じコンポーネントを複数使用したいのです。私はそれらのコンポーネントを XML ファイルを作成しましたが、どれくらいの大きさにすればいいのかわかりません。位置や大きさは後で決めたいのですが(なぜ、サイズを onMeasure であれば onDraw をカスタムコンポーネントクラスに追加し、描画したところ、同様に動作しています。具体的にどのような場合にそうする必要があるのでしょうか?

どのように解決するのですか?

onMeasure() は、親が提供するレイアウト制約に依存するカスタムビューの大きさを Android に伝える機会です。 match_parent の場合よりも wrap_content の状況)。 これらの制約をパッケージ化したものが MeasureSpec の値がメソッドに渡される。 モード値の大まかな相関は以下の通りです。

  • EXACTLY というのは layout_width または layout_height の値が特定の値に設定されました。 ビューをこのサイズにする必要があるでしょう。 これは、次のような場合にも引き起こされることがあります。 match_parent を使用すると、サイズを親ビューに正確に設定できます (これはフレームワークのレイアウトに依存します)。
  • AT_MOST は、通常 layout_width または layout_height の値が設定されました。 match_parent または wrap_content ここで、最大サイズが必要であり(これはフレームワークのレイアウトに依存します)、親ディメンジョンのサイズがその値になります。 このサイズより大きくなってはいけません。
  • 未確定 は、通常 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);
}

お役に立てれば幸いです。