Android 自定义组件不显示其子组件

dea*_*908 0 android custom-component android-custom-view layout-inflater

大家好,我想FieldSet在 Android 中创建一个组件。(类似html),所以像那个。所以我希望我的自定义组件有孩子并有一个板。电路板部分已经完成,但我在显示组件时遇到了一些问题。我正在关注这个答案。这是我的部分:

字段集.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]);
    }
  }
Run Code Online (Sandbox Code Playgroud)

字段集.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>
Run Code Online (Sandbox Code Playgroud)

Android studio 上面的布局预览(貌似组件的布局完全没问题):

在此处输入图片说明

这是我添加它的方法

<?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>
Run Code Online (Sandbox Code Playgroud)

Android Studio 预览如下。(因此布局占用了孩子们需要的所有空间。 另请注意,组件树显示组件TextView按原样添加到布局中。然而,孩子们的高度和宽度为 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>
Run Code Online (Sandbox Code Playgroud)

结果:什么都没有:(,没有评论)

在此处输入图片说明

我也阅读了这个答案并尝试了它,但addView没有帮助 - 它会导致递归并且当我使用addToRoot=True. 我试过LinearLayout,而不是Relative- 不会改变任何东西。我想我在某个地方搞砸了LayoutInflater.from(getContext()) .inflate(R.layout.field_set, this, true);。还值得指出的是,儿童占有一席之地。所以基本上,如果我增加放入 FieldSet 组件的内容的高度,它将需要更多的高度并将下面的所有组件向下推。我闻到了这种Visibility问题。或者某一层低于另一层,儿童的高度和宽度仍然为零。有什么建议?

非常感谢任何形式的帮助。

此致,

Mik*_* M. 7

ViewGroup直接延伸时,您需要自己处理孩子View的测量和布局,否则他们永远不会得到正确的大小或位置。通常,扩展一个ViewGroup已经处理过这些东西的子类会更简单。在这种情况下,您也可以扩展RelativeLayout,因为那是实际保存内部Views 的内容,并且ViewGroup包装它是相当不必要的。

RelativeLayout内部布局 XML 中的 parent则是多余的,可以用<merge>标签替换,这将导致 child在膨胀时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>
Run Code Online (Sandbox Code Playgroud)

我们可以通过在构造函数中设置内部结构并在添加子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);
        }
    }
}
Run Code Online (Sandbox Code Playgroud)