Вы можете получить измерения своего пользовательского представления в 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
предназначен для настройки того, каквыкладываются любые дети по вашему желанию.Он также может вызываться чаще, чем 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");
}
}
Дополнительная информация