我正在尝试创建一个包含 LinearLayout 的自定义 Android 控件。您可以将其视为具有精美边框、背景、左侧图像的扩展 LinearLayout...
我可以用 XML 完成这一切(效果很好)但是因为我的应用程序中出现了很多次,所以很难维护。我认为拥有这样的东西会更好:
/* Main.xml */
<MyFancyLayout>
<TextView /> /* what goes inside my control's linear layout */
</MyfancyLayout>
你会如何处理这个问题?我想避免重写整个线性布局 onMeasure/onLayout 方法。这是我目前拥有的:
/* MyFancyLayout.xml */
<TableLayout>
<ImageView />
<LinearLayout id="container" /> /* where I want the real content to go */
</TableLayout>
和
/* MyFancyLayout.java */
public class MyFancyLayout extends LinearLayout
{
public MyFancyLayout(Context context) {
super(context);
View.inflate(context, R.layout.my_fancy_layout, this);
}
}
如何将用户指定的内容(main.xml 中的 TextView)插入正确的位置 (id=container)?
干杯!
罗曼
-----编辑-------
仍然没有成功,所以我改变了我的设计以使用更简单的布局,并决定接受一些重复的 XML。尽管如此,仍然对任何知道如何执行此操作的人非常感兴趣!
最佳答案
这个确切的问题已经困扰了我一段时间,但直到现在我才解决了它。
乍一看,问题在于声明性内容(在您的情况下为 TextView)是在构造函数之后(我们通常会在其中扩充布局)实例化的,所以它太过分了early 手头有声明和模板内容,可以将前者插入后者。
我找到了一个这样的地方,我们可以在其中操纵两者:它是一个 onFinishInflate() 方法。以下是我的情况:
@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.labeled_layout, this, true);
// Obtain reference to a new container within "template".
final ViewGroup vg = (ViewGroup)template.findViewById(R.id.layout);
index = children.length;
// Push declared children into new container.
while(--index >= 0) {
vg.addView(children[index]);
}
// They suggest to call it no matter what.
super.onFinishInflate();
}
上面引用的 labeled_layout.xml 与下面类似:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation ="vertical"
android:layout_width ="fill_parent"
android:layout_height ="wrap_content"
android:layout_marginLeft ="8dip"
android:layout_marginTop ="3dip"
android:layout_marginBottom ="3dip"
android:layout_weight ="1"
android:duplicateParentState ="true">
<TextView android:id ="@+id/label"
android:layout_width ="fill_parent"
android:layout_height ="wrap_content"
android:singleLine ="true"
android:textAppearance ="?android:attr/textAppearanceMedium"
android:fadingEdge ="horizontal"
android:duplicateParentState="true" />
<LinearLayout
android:id ="@+id/layout"
android:layout_width ="fill_parent"
android:layout_height ="wrap_content"
android:layout_marginLeft ="8dip"
android:layout_marginTop ="3dip"
android:duplicateParentState="true" />
</LinearLayout>
现在(仍然省略了一些细节)我们可能会像这样在其他地方使用它:
<com.example.widget.LabeledLayout
android:layout_width ="fill_parent"
android:layout_height ="wrap_content">
<!-- example content -->
</com.example.widget.LabeledLayout>
关于android - 带 child 的自定义 Android 控件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4604066/