web-dev-qa-db-ja.com

View.onMeasure()はいつ呼び出されますか?

時である

View.onMeasure(int widthMeasureSpec, int heightMeasureSpec)

呼ばれた? onMeasure が呼び出された後にアクションを実行する必要がある Activity があります。

私の質問は ここに投稿された未回答の質問 と同じです。 View のドキュメントには、 requestLayout() が呼び出されたときに onMeasure が呼び出されると記載されています。現在の境界内に収まらなくなりました。

しかし、これは、私のアクティビティがいつ View が測定されたと想定できるかを教えてくれません。私は このコード を拡張して ImageView を使用してTouchImageViewを形成しました。 ここで提案されましたonMeasure メソッドを使用して画像を拡大縮小する必要があります。 ImageView が測定された後に TextView の値を更新して、画像がスケーリングされた割合を表示したいと思います。

24
GregNash

onMeasureは、親ビューがレイアウトを計算する必要があるときに呼び出されます。通常、存在するさまざまな子とそのレイアウトパラメータに応じて、onMeasureが数回呼び出されることがあります。

onMeasure が呼び出されたときに何かを行うための最良の方法は、独自のコントロールを作成して ImageView を拡張し、onMeasureをオーバーライドすることです(super.onMeasureを呼び出して何でもします)それ以外の場合は、実行します)。

その場合、Measureは異なるパラメーターで複数回呼び出される可能性があるため、測定されたものは実際に表示されるものの最終的な幅と高さではない可能性があることに注意してください。

16
Matthieu

カスタムビューの測定値はonSizeChangedで取得できます。

_@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
    super.onSizeChanged(w, h, oldw, oldh);

    // use the provided width and height for whatever you need
}
_

説明

ビューが作成されると、次のメソッドが呼び出される順序になります。

  1. コンストラクタ
    • CustomView(Context context)(プログラムで作成した場合)
    • CustomView(Context context, AttributeSet attrs)(xmlから作成された場合)
  2. onFinishInflate(xmlコンストラクターを使用した場合)
  3. onAttachedToWindow
  4. onMeasure
  5. onSizeChanged
  6. onLayout
  7. onDraw

ビューの測定値を取得できる最も古いのはonMeasureです。その前は、幅と高さは_0_です。ただし、onMeasureで実行する必要があるのは、ビューのサイズを決定することだけです。このメソッドは、ビューが親にどのくらいの大きさになるかを指示している間、何度か呼び出されますが、親は実際の最終的なサイズを決定しています。 (onMeasureの使用方法については この回答 を参照してください。)

測定されたサイズを実際に使用したい場合は、onSizeChangedが最も早い場所です。サイズが_0_からサイズに変化するため、ビューが作成されるたびに呼び出されます。

onLayoutを使用することもできますが、onLayoutはカスタムビューの子のレイアウト方法をカスタマイズするためのものです。たとえば、実際にサイズが変更されていないときにrequestLayout()を呼び出すと、onSizeChangedよりも頻繁に呼び出される可能性があります。

getMeasuredWidth()およびgetMeasuredHeight()を使用して、onDrawのサイズにアクセスすることもできます。ただし、これらを使用して重い計算を行う場合は、事前に行うことをお勧めします。一般的に言えば、onDrawは複数回呼び出される可能性があるため、できるだけ多くしないようにしてください。 (invalidate()が呼び出されるたびに呼び出されます。)

自分で見て

信じられない場合は、以下のカスタムビューで呼び出されるイベントの順序を確認できます。出力は次のとおりです。

_XML constructor called, measured size: (0, 0)
onFinishInflate called, measured size: (0, 0)
onAttachedToWindow called, measured size: (0, 0)
onMeasure called, measured size: (350, 1859)
onMeasure called, measured size: (350, 350)
onMeasure called, measured size: (350, 2112)
onMeasure called, measured size: (350, 350)
onSizeChanged called, measured size: (350, 350)
onLayout called, measured size: (350, 350)
onDraw called, measured size: (350, 350)
_

activity_main.xml

_<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
    xmlns:Android="http://schemas.Android.com/apk/res/Android"
    Android:id="@+id/activity_main"
    Android:layout_width="match_parent"
    Android:layout_height="match_parent">

    <com.example.viewlifecycle.CustomView
        Android:id="@+id/customView"
        Android:layout_width="100dp"
        Android:layout_height="100dp"
        Android:background="@color/colorAccent"/>

</RelativeLayout>
_

CustomView.Java

_public class CustomView extends View {

    private void printLogInfo(String methodName) {
        Log.i("TAG", methodName + " called, measured size: (" + getMeasuredWidth() + ", " + getMeasuredHeight() + ")");
    }

    // constructors

    public CustomView(Context context) {
        super(context);
        printLogInfo("Programmatic constructor");
    }

    public CustomView(Context context, AttributeSet attrs) {
        super(context, attrs);
        printLogInfo("XML constructor");
    }

    // lifecycle methods

    @Override
    protected void onFinishInflate() {
        super.onFinishInflate();
        printLogInfo("onFinishInflate");
    }

    @Override
    protected void onAttachedToWindow() {
        super.onAttachedToWindow();
        printLogInfo("onAttachedToWindow");
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        printLogInfo("onMeasure");
    }

    @Override
    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
        super.onSizeChanged(w, h, oldw, oldh);
        printLogInfo("onSizeChanged");
    }

    @Override
    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
        super.onLayout(changed, left, top, right, bottom);
        printLogInfo("onLayout");
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        printLogInfo("onDraw");
    }
}
_

参考文献

26
Suragch