【发布时间】:2017-04-24 07:57:42
【问题描述】:
大家好,我想在 Android 中创建一个 FieldSet 组件。 (类似于html)所以类似于that。所以我希望我的自定义组件有孩子并有一个板。电路板部分已经完成,但我在显示组件时遇到了一些问题。我正在关注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 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>
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>
结果: 什么都没有:(,没有cmets)
我也阅读了this 的答案并尝试了它,但addView 没有帮助 - 它会导致递归,当我使用addToRoot=True 时不需要它。我试过LinearLayout,而不是Relative - 没有改变任何东西。我想我在LayoutInflater.from(getContext()) .inflate(R.layout.field_set, this, true); 的某个地方搞砸了。还值得指出的是,孩子们占据了位置。所以基本上,如果我增加放入我的 FieldSet 组件的内容的高度,它将需要更多的高度并将所有位于下方的组件向下推。我闻到这种Visibility 的问题。或者某一层低于另一层,孩子的高度和宽度仍然为零。有什么建议吗?
非常感谢任何形式的帮助。
最好的问候,
【问题讨论】:
-
您正在扩展
ViewGroup,因此您必须自己负责测量和布置孩子Views。或者,您可以改为扩展一个ViewGroup子类,该子类已经按照您的意愿处理其子类;例如,FrameLayout、LinearLayout、RelativeLayout等 -
感谢您的回复@Mike。我甚至在发布这个问题之前就尝试扩展不同的类:
View、ViewGroup、LinearLayout、RelativeLayout、FrameLayout。它没有任何改变。我应该实现更多处理绘图的方法吗? (如果是的话,它们应该包含哪些内容) -
现在可能没有。测量和布置孩子可能会很痛苦。如果我是你,我会首先在一个已经处理过这些东西的类中使用它。例如,实际上没有理由不扩展
RelativeLayout,至少,然后去掉膨胀布局中当前作为父级的冗余,并将内部RelativeLayout和TextView包装在<merge>标签中。此外,在通货膨胀之后像这样处理Views 效率有点低,而且不是真正必要的。 -
您可以改为在构造函数中膨胀内部布局,拦截子元素的添加,并从一开始就将它们固定在正确的位置。 This post 会有所帮助,如果你想试一试的话。除此之外,对于像这样的自定义
ViewGroups,我建议不要在测试时包装宽度或高度,可能使用明确的测量值,也使用对比背景颜色,确保文本颜色不混合等等。可以更轻松地查看正在发生的事情。 -
@Mike,非常感谢你的帮助,你让我很开心。所以我在这里犯了3个错误:1)我应该在构造函数中膨胀布局。 2)我应该在我的 xml 中使用合并作为父元素 3)我应该覆盖
addView方法来添加子元素,而不是手动重新附加它们,如果您在下面发布您的答案,我将其标记为已接受并投票。
标签: android android-custom-view custom-component layout-inflater