Android 自定义组件未显示其 children
Android custom component doesn't display its children
大家好,我想在 Android 中创建一个 FieldSet
组件。 (类似于 html
)所以类似于 that. So I want my custom component to have children and to have a board. The board part is done already, but I have some issues with display the component. I'm following this 的答案。这是我的部分:
FieldSet.java:
public class FieldSet extends ViewGroup {
//... 3 constructors
@Override
protected void onFinishInflate()
int index = getChildCount();
// Collect children declared in XML.
View[] children = new View[index];
while(--index >= 0) {
children[index] = getChildAt(index);
}
// Pressumably, wipe out existing content (still holding reference to it).
this.detachAllViewsFromParent();
// Inflate new "template".
final View template = LayoutInflater.from(getContext()).inflate(R.layout.field_set, this, true);
// Obtain reference to a new container within "template".
final ViewGroup vg = (ViewGroup)template.findViewById(R.id.field_set_content);
index = children.length;
// Push declared children into new container.
while(--index >= 0) {
vg.addView(children[index]);
}
}
field_set.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:duplicateParentState ="true"
android:layout_height="wrap_content">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="15dp"
android:id="@+id/field_set_content"
android:duplicateParentState ="true"
android:background="@drawable/field_set_frame"
android:orientation="vertical"
android:padding="20dp">
</RelativeLayout>
<!-- This is the title label -->
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="50dp"
android:paddingLeft="50dp"
android:paddingRight="50dp"
android:layout_marginRight="50dp"
android:layout_centerHorizontal="true"
android:text="Label"
android:background="@color/colorLoginBlue"
android:padding="5dp"
android:id="@+id/field_set_label"
android:textColor="@color/colorSmallTxt" />
</RelativeLayout>
Android工作室上面的布局预览(好像组件的布局完全没问题):
我是这样添加的:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout 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"
xmlns:fs="http://schemas.android.com/apk/res-auto"
tools:context="my.package.DeleteThis">
<my.package.FieldSet
android:layout_width="match_parent"
fs:label="Injected Label"
android:layout_height="wrap_content"
android:gravity="bottom">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="50sp"
android:text="Inner text" />
</my.package.FieldSet>
<TextView
android:layout_width="match_parent"
android:text="BELOW"
android:layout_height="wrap_content" />
</RelativeLayout>
Android 工作室预览如下。 (所以布局采用 children 需要的所有 space。还要注意组件树显示组件 TextView
被添加到布局中,因为它应该是 . 然而 children 的高度和宽度为 0:
field_set_frame.xml:
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item>
<shape android:shape="rectangle" >
<corners android:radius="7dp" />
<padding android:bottom="2dp"/>
<padding android:right="2dp"/>
<padding android:left="2dp"/>
<padding android:top="2dp"/>
<stroke android:width="1dp" android:color="@color/colorFieldSetBorder" />
</shape>
</item>
</selector>
结果:
什么都没有:(, 没有评论)
我也阅读了 this 的答案并尝试了它,但是 addView
没有帮助 - 它导致递归并且当我使用 addToRoot=True
时不需要它。我试过 LinearLayout
,而不是 Relative
- 没有改变任何东西。我想我在 LayoutInflater.from(getContext()) .inflate(R.layout.field_set, this, true);
的某个地方搞砸了。还值得指出的是 children 占据了位置。所以基本上,如果我增加我放入我的 FieldSet 组件的内容的高度,它会占用更多的高度并将下面的所有组件向下推。我觉得有点 Visibility
问题。或者某层低于另一层,孩子的高度和宽度仍然为零。有什么建议吗?
非常感谢任何形式的帮助。
此致,
直接扩展 ViewGroup
时,您需要自己处理子 View
的测量和布局,否则它们永远无法正确调整大小或位置。通常,扩展一个已经处理这些东西的 ViewGroup
子类会更简单。在这种情况下,您还不如扩展 RelativeLayout
,因为这实际上是内部 View
的内容,而 ViewGroup
包装它是相当不必要的。
内部布局XML中的父RelativeLayout
是冗余的,可以用<merge>
标签替换,这将导致子View
被膨胀后直接添加到您的 RelativeLayout
子类。
<merge xmlns:android="http://schemas.android.com/apk/res/android">
<RelativeLayout
android:id="@+id/field_set_content"
... />
<TextView
android:id="@+id/field_set_label"
... />
</merge>
我们可以进一步简化事情,方法是在构造函数中设置内部结构,并在添加子 View
时将它们放在正确的位置,而不是杂耍所有这些在 onFinishInflate()
。例如:
public class FieldSet extends RelativeLayout {
final ViewGroup vg;
public FieldSet(Context context, AttributeSet attrs) {
super(context, attrs);
LayoutInflater.from(context).inflate(R.layout.field_set, this, true);
vg = (ViewGroup) findViewById(R.id.field_set_content);
}
@Override
public void addView(View child, int index, ViewGroup.LayoutParams params) {
final int id = child.getId();
if (id == R.id.field_set_content || id == R.id.field_set_label) {
super.addView(child, index, params);
}
else {
vg.addView(child, index, params);
}
}
}
大家好,我想在 Android 中创建一个 FieldSet
组件。 (类似于 html
)所以类似于 that. So I want my custom component to have children and to have a board. The board part is done already, but I have some issues with display the component. I'm following this 的答案。这是我的部分:
FieldSet.java:
public class FieldSet extends ViewGroup {
//... 3 constructors
@Override
protected void onFinishInflate()
int index = getChildCount();
// Collect children declared in XML.
View[] children = new View[index];
while(--index >= 0) {
children[index] = getChildAt(index);
}
// Pressumably, wipe out existing content (still holding reference to it).
this.detachAllViewsFromParent();
// Inflate new "template".
final View template = LayoutInflater.from(getContext()).inflate(R.layout.field_set, this, true);
// Obtain reference to a new container within "template".
final ViewGroup vg = (ViewGroup)template.findViewById(R.id.field_set_content);
index = children.length;
// Push declared children into new container.
while(--index >= 0) {
vg.addView(children[index]);
}
}
field_set.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:duplicateParentState ="true"
android:layout_height="wrap_content">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="15dp"
android:id="@+id/field_set_content"
android:duplicateParentState ="true"
android:background="@drawable/field_set_frame"
android:orientation="vertical"
android:padding="20dp">
</RelativeLayout>
<!-- This is the title label -->
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="50dp"
android:paddingLeft="50dp"
android:paddingRight="50dp"
android:layout_marginRight="50dp"
android:layout_centerHorizontal="true"
android:text="Label"
android:background="@color/colorLoginBlue"
android:padding="5dp"
android:id="@+id/field_set_label"
android:textColor="@color/colorSmallTxt" />
</RelativeLayout>
Android工作室上面的布局预览(好像组件的布局完全没问题):
我是这样添加的:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout 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"
xmlns:fs="http://schemas.android.com/apk/res-auto"
tools:context="my.package.DeleteThis">
<my.package.FieldSet
android:layout_width="match_parent"
fs:label="Injected Label"
android:layout_height="wrap_content"
android:gravity="bottom">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="50sp"
android:text="Inner text" />
</my.package.FieldSet>
<TextView
android:layout_width="match_parent"
android:text="BELOW"
android:layout_height="wrap_content" />
</RelativeLayout>
Android 工作室预览如下。 (所以布局采用 children 需要的所有 space。还要注意组件树显示组件 TextView
被添加到布局中,因为它应该是 . 然而 children 的高度和宽度为 0:
field_set_frame.xml:
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item>
<shape android:shape="rectangle" >
<corners android:radius="7dp" />
<padding android:bottom="2dp"/>
<padding android:right="2dp"/>
<padding android:left="2dp"/>
<padding android:top="2dp"/>
<stroke android:width="1dp" android:color="@color/colorFieldSetBorder" />
</shape>
</item>
</selector>
结果: 什么都没有:(, 没有评论)
我也阅读了 this 的答案并尝试了它,但是 addView
没有帮助 - 它导致递归并且当我使用 addToRoot=True
时不需要它。我试过 LinearLayout
,而不是 Relative
- 没有改变任何东西。我想我在 LayoutInflater.from(getContext()) .inflate(R.layout.field_set, this, true);
的某个地方搞砸了。还值得指出的是 children 占据了位置。所以基本上,如果我增加我放入我的 FieldSet 组件的内容的高度,它会占用更多的高度并将下面的所有组件向下推。我觉得有点 Visibility
问题。或者某层低于另一层,孩子的高度和宽度仍然为零。有什么建议吗?
非常感谢任何形式的帮助。
此致,
直接扩展 ViewGroup
时,您需要自己处理子 View
的测量和布局,否则它们永远无法正确调整大小或位置。通常,扩展一个已经处理这些东西的 ViewGroup
子类会更简单。在这种情况下,您还不如扩展 RelativeLayout
,因为这实际上是内部 View
的内容,而 ViewGroup
包装它是相当不必要的。
内部布局XML中的父RelativeLayout
是冗余的,可以用<merge>
标签替换,这将导致子View
被膨胀后直接添加到您的 RelativeLayout
子类。
<merge xmlns:android="http://schemas.android.com/apk/res/android">
<RelativeLayout
android:id="@+id/field_set_content"
... />
<TextView
android:id="@+id/field_set_label"
... />
</merge>
我们可以进一步简化事情,方法是在构造函数中设置内部结构,并在添加子 View
时将它们放在正确的位置,而不是杂耍所有这些在 onFinishInflate()
。例如:
public class FieldSet extends RelativeLayout {
final ViewGroup vg;
public FieldSet(Context context, AttributeSet attrs) {
super(context, attrs);
LayoutInflater.from(context).inflate(R.layout.field_set, this, true);
vg = (ViewGroup) findViewById(R.id.field_set_content);
}
@Override
public void addView(View child, int index, ViewGroup.LayoutParams params) {
final int id = child.getId();
if (id == R.id.field_set_content || id == R.id.field_set_label) {
super.addView(child, index, params);
}
else {
vg.addView(child, index, params);
}
}
}