在自定义 ViewGroup 中使用 onLayout 正确布局子项
Correctly layout children with onLayout in Custom ViewGroup
我正在创建自定义 ViewGroup。我确实需要一个在另一个之上的 2 FrameLayout;留在底部的一个必须是 20dp,而另一个必须覆盖视图的其余部分。
onMeasure
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int widthMode = MeasureSpec.getMode(widthMeasureSpec);
int heightMode = MeasureSpec.getMode(heightMeasureSpec);
int widthSize = MeasureSpec.getSize(widthMeasureSpec);
int heightSize = MeasureSpec.getSize(heightMeasureSpec);
setMeasuredDimension(widthSize, heightSize);
final View content = getChildAt(CONTENT_INDEX);
final View bar = getChildAt(BAR_INDEX);
content.measure(
MeasureSpec.makeMeasureSpec(widthSize, MeasureSpec.EXACTLY),
MeasureSpec.makeMeasureSpec(heightSize - getPixels(BAR_HEIGHT), MeasureSpec.EXACTLY)
);
bar.measure(
MeasureSpec.makeMeasureSpec(widthSize, MeasureSpec.EXACTLY),
MeasureSpec.makeMeasureSpec(getPixels(BAR_HEIGHT), MeasureSpec.EXACTLY)
);
onLayout
@Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
mInLayout = true;
final View content = getChildAt(CONTENT_INDEX);
final View bar = getChildAt(BAR_INDEX);
if (content.getVisibility() != GONE) {
content.layout(0, 0, content.getMeasuredWidth(), content.getMeasuredHeight());
}
if (bar.getVisibility() != GONE) {
bar.layout(0, content.getMeasuredHeight(), bar.getMeasuredWidth(), 0);
}
mInLayout = false;
mFirstLayout = false;
}
}
我添加到这个自定义 ViewGroup 的视图
LayoutParams lp = new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT);
mContentContainer = new FrameLayout(getContext());
mContentContainer.setLayoutParams(lp);
mBarContainer = new FrameLayout(getContext());
mBarContainer.setLayoutParams(lp);
// ... adding stuff to both containers ....
addView(mContentContainer, 0);
addView(mBarContainer, 1);
问题
mContentContainer
正确呈现(从 top=0 到 bottom=(totalHeight - bar height) 并匹配父级的宽度),而 bar 未呈现。
View#layout()
方法中的最后一个参数是View
的底部。对于你的 bar
,你超过了 0
,但它应该是你自定义的 View
的高度,你可以从 t
和 b
中计算出来传递给 onLayout()
.
的值
bar.layout(0, content.getMeasuredHeight(), bar.getMeasuredWidth(), b - t);
我正在创建自定义 ViewGroup。我确实需要一个在另一个之上的 2 FrameLayout;留在底部的一个必须是 20dp,而另一个必须覆盖视图的其余部分。
onMeasure
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int widthMode = MeasureSpec.getMode(widthMeasureSpec);
int heightMode = MeasureSpec.getMode(heightMeasureSpec);
int widthSize = MeasureSpec.getSize(widthMeasureSpec);
int heightSize = MeasureSpec.getSize(heightMeasureSpec);
setMeasuredDimension(widthSize, heightSize);
final View content = getChildAt(CONTENT_INDEX);
final View bar = getChildAt(BAR_INDEX);
content.measure(
MeasureSpec.makeMeasureSpec(widthSize, MeasureSpec.EXACTLY),
MeasureSpec.makeMeasureSpec(heightSize - getPixels(BAR_HEIGHT), MeasureSpec.EXACTLY)
);
bar.measure(
MeasureSpec.makeMeasureSpec(widthSize, MeasureSpec.EXACTLY),
MeasureSpec.makeMeasureSpec(getPixels(BAR_HEIGHT), MeasureSpec.EXACTLY)
);
onLayout
@Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
mInLayout = true;
final View content = getChildAt(CONTENT_INDEX);
final View bar = getChildAt(BAR_INDEX);
if (content.getVisibility() != GONE) {
content.layout(0, 0, content.getMeasuredWidth(), content.getMeasuredHeight());
}
if (bar.getVisibility() != GONE) {
bar.layout(0, content.getMeasuredHeight(), bar.getMeasuredWidth(), 0);
}
mInLayout = false;
mFirstLayout = false;
}
}
我添加到这个自定义 ViewGroup 的视图
LayoutParams lp = new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT);
mContentContainer = new FrameLayout(getContext());
mContentContainer.setLayoutParams(lp);
mBarContainer = new FrameLayout(getContext());
mBarContainer.setLayoutParams(lp);
// ... adding stuff to both containers ....
addView(mContentContainer, 0);
addView(mBarContainer, 1);
问题
mContentContainer
正确呈现(从 top=0 到 bottom=(totalHeight - bar height) 并匹配父级的宽度),而 bar 未呈现。
View#layout()
方法中的最后一个参数是View
的底部。对于你的 bar
,你超过了 0
,但它应该是你自定义的 View
的高度,你可以从 t
和 b
中计算出来传递给 onLayout()
.
bar.layout(0, content.getMeasuredHeight(), bar.getMeasuredWidth(), b - t);