您可以在onSizeChanged
方法中获取自定义视图的尺寸。
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
}
解释
创建视图时,以下方法的调用顺序如下:
- 构造函数
CustomView(Context context)
(如果是以编程方式创建的)
CustomView(Context context, AttributeSet attrs)
(如果从xml创建)
onFinishInflate
(假设您使用了xml构造函数)
onAttachedToWindow
onMeasure
onSizeChanged
onLayout
onDraw
您可以在onMeasure
中获得该视图的测量尺寸,此之前宽度和高度都为0
。然而,在onMeasure
中应该做的唯一事情就是确定视图的大小。在视图告诉父级其想要有多大之后,该方法会被多次调用,但是父级会确定实际的最终大小。(有关onMeasure
的正确用法,请参见此答案。)
如果您想要真正使用测量到的大小,则最早可以在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() + ")");
}
public CustomView(Context context) {
super(context);
printLogInfo("Programmatic constructor");
}
public CustomView(Context context, AttributeSet attrs) {
super(context, attrs);
printLogInfo("XML constructor");
}
@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");
}
}
更多阅读