時である
View.onMeasure(int widthMeasureSpec, int heightMeasureSpec)
呼ばれた? onMeasure が呼び出された後にアクションを実行する必要がある Activity があります。
私の質問は ここに投稿された未回答の質問 と同じです。 View のドキュメントには、 requestLayout() が呼び出されたときに onMeasure が呼び出されると記載されています。現在の境界内に収まらなくなりました。
しかし、これは、私のアクティビティがいつ View が測定されたと想定できるかを教えてくれません。私は このコード を拡張して ImageView を使用してTouchImageViewを形成しました。 ここで提案されましたonMeasure メソッドを使用して画像を拡大縮小する必要があります。 ImageView が測定された後に TextView の値を更新して、画像がスケーリングされた割合を表示したいと思います。
onMeasureは、親ビューがレイアウトを計算する必要があるときに呼び出されます。通常、存在するさまざまな子とそのレイアウトパラメータに応じて、onMeasureが数回呼び出されることがあります。
onMeasure が呼び出されたときに何かを行うための最良の方法は、独自のコントロールを作成して ImageView を拡張し、onMeasureをオーバーライドすることです(super.onMeasureを呼び出して何でもします)それ以外の場合は、実行します)。
その場合、Measureは異なるパラメーターで複数回呼び出される可能性があるため、測定されたものは実際に表示されるものの最終的な幅と高さではない可能性があることに注意してください。
カスタムビューの測定値は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
}
_
ビューが作成されると、次のメソッドが呼び出される順序になります。
CustomView(Context context)
(プログラムで作成した場合)CustomView(Context context, AttributeSet attrs)
(xmlから作成された場合)onFinishInflate
(xmlコンストラクターを使用した場合)onAttachedToWindow
onMeasure
onSizeChanged
onLayout
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");
}
}
_