Android自定义组件不显示其子级 [英] Android custom component doesn't display its children
问题描述
大家好,我想在Android中创建一个FieldSet
组件. (类似于html
),例如那.因此,我希望我的自定义组件有孩子并有一块木板.电路板零件已经完成,但是在显示组件时遇到一些问题.我正在关注此答案.这是我的部分:
Hi guys I want to create a FieldSet
component in Android. (similar to html
) so something like 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 answer. Here're my parts:
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 Studio上方的布局预览(似乎组件的布局完全没问题):
Android studio above's layout preview (seems like component's layout is completely fine):
这是我的添加方式:
<?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 Studio预览在下面. (因此,布局占用了孩子所需的所有空间.还请注意,组件树显示组件TextView
已添加到布局中,应按其原样.尽管如此,孩子的高度和宽度为0:
Android studio preview is below. (So the layout takes all space that children need. Also note that component tree shows that component TextView
is added as to Layout as it should be . Nevertheless children have 0 height and width:
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>
结果: 只是一无所有:(,没有评论)
RESULT: Just nothing:(, no comments)
我还阅读了此答案,并尝试了它,但是addView
并没有帮助-它会导致递归,而当我使用addToRoot=True
时则不需要.我尝试使用LinearLayout
而不是Relative
-不会更改任何内容.我想我在LayoutInflater.from(getContext()) .inflate(R.layout.field_set, this, true);
中的某个地方搞砸了.还值得指出的是,孩子们占据了地方.因此,基本上,如果我增加放入FieldSet组件中的内容的高度,它将占用更多的高度,并将下面的所有组件向下推.我感到这种Visibility
问题.或某层低于另一层,孩子的高度和宽度仍为零.有什么建议吗?
I also read this answer and tried it, but addView
didnt help - it causes recursion and it's not needed when I use addToRoot=True
. I tried LinearLayout
, instead of Relative
- doesnt change anything. I think I screw up somewhere in LayoutInflater.from(getContext()) .inflate(R.layout.field_set, this, true);
. It's also worth to point out that children occupy place. So basically if I increase the height of content that I put into my FieldSet component, it will take more height and push all components that are beneath down. I smeel this kinda of Visibility
issue. Or some layer goes below another one, still height and width of chidren are zeros. Any suggestions?
任何帮助都将不胜感激.
Any kind of help is greatly appreciated.
最诚挚的问候,
推荐答案
直接扩展ViewGroup
时,您需要自己测量和布置孩子View
的布局,否则他们的尺寸或位置永远不会正确.通常,扩展已经处理了这些内容的ViewGroup
子类更为简单.在这种情况下,您最好扩展RelativeLayout
,因为这实际上是保存内部View
的内容,而ViewGroup
包装它是不必要的.
When extending ViewGroup
directly, you need to handle measuring and laying out the child View
s yourself, or they never get sized or positioned correctly. Oftentimes, it's simpler to extend a ViewGroup
subclass that already handles that stuff. In this case, you might as well extend RelativeLayout
, since that's what's actually holding the internal View
s, and the ViewGroup
wrapping it is rather unnecessary.
内部布局XML中的父级RelativeLayout
然后是多余的,并且可以替换为<merge>
标记,这将导致子级View
在膨胀时直接添加到您的RelativeLayout
子类中. /p>
The parent RelativeLayout
in the internal layout XML is then redundant, and can be replaced with <merge>
tags, which will cause the child View
s to be added directly to your RelativeLayout
subclass when inflated.
<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()
中将所有内容混为一谈.例如:
We can further simplify things by setting up the internal structure in the constructor(s), and putting the child View
s in the right place as they're added, rather than juggling all of that around in onFinishInflate()
. For example:
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自定义组件不显示其子级的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!