android 自定义组视图布局不正确
android Custom group view doesn't lay out correctly
我创建了这个自定义视图组:
public class CustomGroupView extends ViewGroup {
public static final String TAG = "CustomGroupView";
public CustomGroupView(Context context) {
this(context, null);
}
public CustomGroupView(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public CustomGroupView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
Log.d(TAG, "onMeasure");
int childrenCount = getChildCount();
// measure all children
for(int i=0; i<childrenCount; i++) {
final View child = getChildAt(i);
measureChild(child, widthMeasureSpec, heightMeasureSpec);
}
// the height and the width of the overall group view is
// the height and the width of the last child
View lastChild = getChildAt(childrenCount-1);
int overallHeight = lastChild.getMeasuredHeight();
int overallWidth = lastChild.getMeasuredWidth();
Log.d(TAG, "overallHeight: " + overallHeight + "; overallWidth: " + overallWidth);
setMeasuredDimension(resolveSize(overallWidth, widthMeasureSpec), resolveSize(overallHeight, heightMeasureSpec));
}
@Override
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
Log.d(TAG, "onLayout");
Log.d(TAG, "left: " + left + "; top: " + top + "; right: " + right + "; bottom: " + bottom);
int childrenCount = getChildCount();
// all children will be aligned to the top
for(int i=0; i<childrenCount; i++) {
final View child = getChildAt(i);
int childLeft = left;
int childTop = top;
int childRight = left + child.getMeasuredWidth();
int childBottom = top + child.getMeasuredHeight();
Log.d("TAG", "child #: " + i + "; left: " + childLeft + "; top: " + childTop + "; right: " + childRight +"; bottom: " + childBottom);
child.layout(childLeft, childTop, childRight, childBottom);
}
}
}
我发现当我将它放入 LinearLayout 容器时它的行为很奇怪。
正确工作时的示例:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context=".MainActivity">
<org.test.oct9customgroup.CustomGroupView
android:layout_width="match_parent"
android:layout_height="wrap_content">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:alpha="1"
android:background="#4c4c4c"
android:scaleX="0.6"
android:padding="8dp"
android:text="1"
android:textSize="32sp"/>
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:alpha="0.7"
android:background="#ffffa3"
android:scaleX="0.75"
android:padding="8dp"
android:text="2"
android:textSize="32sp"/>
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:alpha="0.7"
android:background="#fce5e8"
android:scaleX="0.9"
android:padding="8dp"
android:text="3"
android:textSize="32sp"/>
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:alpha="0.4"
android:background="#b3ffc3"
android:padding="32dp"
android:text="Last child's text"
android:textSize="32sp"/>
</org.test.oct9customgroup.CustomGroupView>
<TextView
android:id="@+id/top_textview"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textSize="50sp"
android:background="#CCCCCC"
android:text="Top text"/>
</LinearLayout>
但是如果我更改自定义视图组和文本视图的顺序:
<LinearLayout>
<TextView/>
<org.test.oct9customgroup.CustomGroupView>
<TextView/>
<TextView/>
<TextView/>
<TextView/>
</org.test.oct9customgroup.CustomGroupView>
</LinearLayout>
问题:那个文本视图和我的组视图之间出现了很大的差距,我不知道如何摆脱它。
图片和日志:
一切正常时记录:
10-09 15:54:08.922 18046-18046/org.test.viewsexperiments D/CustomGroupView: onMeasure
10-09 15:54:08.922 18046-18046/org.test.viewsexperiments D/CustomGroupView: overallHeight: 144; overallWidth: 800
10-09 15:54:08.924 18046-18046/org.test.viewsexperiments D/CustomGroupView: onLayout
10-09 15:54:08.925 18046-18046/org.test.viewsexperiments D/CustomGroupView: left: 0; top: 0; right: 800; bottom: 144
10-09 15:54:08.925 18046-18046/org.test.viewsexperiments D/CustomGroupView: child #: 0; left: 0; top: 0; right: 800; bottom: 80
10-09 15:54:08.926 18046-18046/org.test.viewsexperiments D/CustomGroupView: child #: 1; left: 0; top: 0; right: 800; bottom: 80
10-09 15:54:08.926 18046-18046/org.test.viewsexperiments D/CustomGroupView: child #: 2; left: 0; top: 0; right: 800; bottom: 80
10-09 15:54:08.926 18046-18046/org.test.viewsexperiments D/CustomGroupView: child #: 3; left: 0; top: 0; right: 800; bottom: 144
出现间隙时记录:
10-09 15:59:24.202 27506-27506/? D/CustomGroupView: onMeasure
10-09 15:59:24.202 27506-27506/? D/CustomGroupView: overallHeight: 144; overallWidth: 800
10-09 15:59:24.203 27506-27506/? D/CustomGroupView: onLayout
10-09 15:59:24.204 27506-27506/? D/CustomGroupView: left: 0; top: 90; right: 800; bottom: 234
10-09 15:59:24.204 27506-27506/? D/CustomGroupView: child #: 0; left: 0; top: 90; right: 800; bottom: 170
10-09 15:59:24.204 27506-27506/? D/CustomGroupView: child #: 1; left: 0; top: 90; right: 800; bottom: 170
10-09 15:59:24.204 27506-27506/? D/CustomGroupView: child #: 2; left: 0; top: 90; right: 800; bottom: 170
10-09 15:59:24.205 27506-27506/? D/CustomGroupView: child #: 3; left: 0; top: 90; right: 800; bottom: 234
你能告诉我为什么会这样吗?
编辑 结果发现间隙的高度等于我自定义组视图上方的TextView的高度。
我想在我的自定义组视图的 canvas 子级上绘图时会发生一些变化。
可能绘图应该从 (0, 0) 开始,但它从 (0, top) 点开始。
有没有人知道如何解决它?
编辑2添加红色背景后
<org.test.oct9customgroup.CustomGroupView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#ff0000">
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
这四个位置是 CustomGroupView
与其父级之间的距离,因此在布置子级时使用它们没有任何意义。代码应该是:
int childLeft = 0;
int childTop = 0;
int childRight = childLeft + child.getMeasuredWidth();
int childBottom = childTop + child.getMeasuredHeight();
ViewGroup
由其父级正确布局。错误是你需要
int childTop = 0;
而不是
int childTop = top;
在你的 onLayout
中。 onLayout提供的四个值都是相对于parent
我创建了这个自定义视图组:
public class CustomGroupView extends ViewGroup {
public static final String TAG = "CustomGroupView";
public CustomGroupView(Context context) {
this(context, null);
}
public CustomGroupView(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public CustomGroupView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
Log.d(TAG, "onMeasure");
int childrenCount = getChildCount();
// measure all children
for(int i=0; i<childrenCount; i++) {
final View child = getChildAt(i);
measureChild(child, widthMeasureSpec, heightMeasureSpec);
}
// the height and the width of the overall group view is
// the height and the width of the last child
View lastChild = getChildAt(childrenCount-1);
int overallHeight = lastChild.getMeasuredHeight();
int overallWidth = lastChild.getMeasuredWidth();
Log.d(TAG, "overallHeight: " + overallHeight + "; overallWidth: " + overallWidth);
setMeasuredDimension(resolveSize(overallWidth, widthMeasureSpec), resolveSize(overallHeight, heightMeasureSpec));
}
@Override
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
Log.d(TAG, "onLayout");
Log.d(TAG, "left: " + left + "; top: " + top + "; right: " + right + "; bottom: " + bottom);
int childrenCount = getChildCount();
// all children will be aligned to the top
for(int i=0; i<childrenCount; i++) {
final View child = getChildAt(i);
int childLeft = left;
int childTop = top;
int childRight = left + child.getMeasuredWidth();
int childBottom = top + child.getMeasuredHeight();
Log.d("TAG", "child #: " + i + "; left: " + childLeft + "; top: " + childTop + "; right: " + childRight +"; bottom: " + childBottom);
child.layout(childLeft, childTop, childRight, childBottom);
}
}
}
我发现当我将它放入 LinearLayout 容器时它的行为很奇怪。
正确工作时的示例:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context=".MainActivity">
<org.test.oct9customgroup.CustomGroupView
android:layout_width="match_parent"
android:layout_height="wrap_content">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:alpha="1"
android:background="#4c4c4c"
android:scaleX="0.6"
android:padding="8dp"
android:text="1"
android:textSize="32sp"/>
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:alpha="0.7"
android:background="#ffffa3"
android:scaleX="0.75"
android:padding="8dp"
android:text="2"
android:textSize="32sp"/>
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:alpha="0.7"
android:background="#fce5e8"
android:scaleX="0.9"
android:padding="8dp"
android:text="3"
android:textSize="32sp"/>
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:alpha="0.4"
android:background="#b3ffc3"
android:padding="32dp"
android:text="Last child's text"
android:textSize="32sp"/>
</org.test.oct9customgroup.CustomGroupView>
<TextView
android:id="@+id/top_textview"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textSize="50sp"
android:background="#CCCCCC"
android:text="Top text"/>
</LinearLayout>
但是如果我更改自定义视图组和文本视图的顺序:
<LinearLayout>
<TextView/>
<org.test.oct9customgroup.CustomGroupView>
<TextView/>
<TextView/>
<TextView/>
<TextView/>
</org.test.oct9customgroup.CustomGroupView>
</LinearLayout>
问题:那个文本视图和我的组视图之间出现了很大的差距,我不知道如何摆脱它。
图片和日志:
一切正常时记录:
10-09 15:54:08.922 18046-18046/org.test.viewsexperiments D/CustomGroupView: onMeasure
10-09 15:54:08.922 18046-18046/org.test.viewsexperiments D/CustomGroupView: overallHeight: 144; overallWidth: 800
10-09 15:54:08.924 18046-18046/org.test.viewsexperiments D/CustomGroupView: onLayout
10-09 15:54:08.925 18046-18046/org.test.viewsexperiments D/CustomGroupView: left: 0; top: 0; right: 800; bottom: 144
10-09 15:54:08.925 18046-18046/org.test.viewsexperiments D/CustomGroupView: child #: 0; left: 0; top: 0; right: 800; bottom: 80
10-09 15:54:08.926 18046-18046/org.test.viewsexperiments D/CustomGroupView: child #: 1; left: 0; top: 0; right: 800; bottom: 80
10-09 15:54:08.926 18046-18046/org.test.viewsexperiments D/CustomGroupView: child #: 2; left: 0; top: 0; right: 800; bottom: 80
10-09 15:54:08.926 18046-18046/org.test.viewsexperiments D/CustomGroupView: child #: 3; left: 0; top: 0; right: 800; bottom: 144
出现间隙时记录:
10-09 15:59:24.202 27506-27506/? D/CustomGroupView: onMeasure
10-09 15:59:24.202 27506-27506/? D/CustomGroupView: overallHeight: 144; overallWidth: 800
10-09 15:59:24.203 27506-27506/? D/CustomGroupView: onLayout
10-09 15:59:24.204 27506-27506/? D/CustomGroupView: left: 0; top: 90; right: 800; bottom: 234
10-09 15:59:24.204 27506-27506/? D/CustomGroupView: child #: 0; left: 0; top: 90; right: 800; bottom: 170
10-09 15:59:24.204 27506-27506/? D/CustomGroupView: child #: 1; left: 0; top: 90; right: 800; bottom: 170
10-09 15:59:24.204 27506-27506/? D/CustomGroupView: child #: 2; left: 0; top: 90; right: 800; bottom: 170
10-09 15:59:24.205 27506-27506/? D/CustomGroupView: child #: 3; left: 0; top: 90; right: 800; bottom: 234
你能告诉我为什么会这样吗?
编辑 结果发现间隙的高度等于我自定义组视图上方的TextView的高度。
我想在我的自定义组视图的 canvas 子级上绘图时会发生一些变化。
可能绘图应该从 (0, 0) 开始,但它从 (0, top) 点开始。
有没有人知道如何解决它?
编辑2添加红色背景后
<org.test.oct9customgroup.CustomGroupView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#ff0000">
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
这四个位置是 CustomGroupView
与其父级之间的距离,因此在布置子级时使用它们没有任何意义。代码应该是:
int childLeft = 0;
int childTop = 0;
int childRight = childLeft + child.getMeasuredWidth();
int childBottom = childTop + child.getMeasuredHeight();
ViewGroup
由其父级正确布局。错误是你需要
int childTop = 0;
而不是
int childTop = top;
在你的 onLayout
中。 onLayout提供的四个值都是相对于parent