自定义Android控件带孩子

我正在尝试创建一个包含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);
    }
}

您将如何在正确的位置(id = container)中插入用户指定的内容(main.xml中的T​​extView)?

干杯!

罗曼

—–编辑——-

仍然没有运气,所以我改变了我的设计,使用一个更简单的布局,并决定生活与一些重复的XML.对任何人仍然很有兴趣知道如何做到这一点!

解决方法

这个确切的问题已经让我有一段时间了,但现在我已经解决了这个问题.

乍一看,问题在于,在ctor之后的某个时间(在我们通常会膨胀我们的布局)的时候,声明性内容(您的案例中的TextView)被实例化,所以现在还有声明和模板内容的时间太早了将前者推入后者.

我找到了一个这样的地方,我们可以操纵这两个:这是一个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>

相关文章

ADB Remote ATV Android TV 的遥控器,基于 ADB Shell 命令 ...
使用Flutter自带的SearchDelegate组件实现搜索界面,通过魔改...
上篇文章讲解了怎么使用Kotlin的协程配合Retrofit发起网络请...
安卓开发——WebView+Recyclerview文章详情页,解决高度...
Android 如何解决dialog弹出时无法捕捉Activity的back事件 在...