什么时候
View.onMeasure(int widthMeasureSpec, int heightMeasureSpec)
叫什么?我有Activity需要在调用onMeasure后执行操作。
我的问题与the unanswered question posted here相同。 View文档声明onMeasure在调用requestLayout()时被调用,当它认为它不再适合其当前范围时,它本身就被一个视图调用。
然而,这并没有告诉我何时我的活动可以假设我的View已被测量。我已使用this code扩展ImageView以形成TouchImageView。 It was suggested here我应该使用onMeasure方法来扩展我的形象。我希望在测量TextView之后更新ImageView的值,以便显示缩放图像的百分比。
答案 0 :(得分:15)
您可以在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
的使用方式,请参阅this answer。)
如果您想实际使用测量的尺寸,最早的地方是onSizeChanged
。每当创建视图时都会调用它,因为大小从0
变为任何大小。
您也可以使用onLayout
,但据我了解,onLayout
用于自定义自定义视图的任何子项的布局方式。它也可能比onSizeChanged
更频繁地被调用,例如,如果在实际没有更改大小时调用requestLayout()
。
您还可以使用onDraw
和getMeasuredWidth()
访问getMeasuredHeight()
中的尺寸。但是,如果您使用它们进行任何繁重的计算,最好事先做好。一般来说,尽量保持尽可能多的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");
}
}
答案 1 :(得分:14)