带孩子的自定义Android控件 [英] Custom Android control with children

查看:56
本文介绍了带孩子的自定义Android控件的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试创建一个自定义Android控件,该控件包含LinearLayout .您可以将其视为具有精美边框,背景,左侧图像的扩展LinearLayout.

I'm trying to create a custom Android control that contains a LinearLayout. You can think of it as an extended LinearLayout with fancy borders, a background, an image on the left...

我可以使用XML来完成所有工作(效果很好),但是由于我的应用程序中发生了很多事,因此很难维护.我认为拥有这样的东西会更好:

I could do it all in XML (works great) but since I have dozens of occurences in my app it's getting hard to maintain. I thought it would be nicer to have something like this:

/* Main.xml */
<MyFancyLayout>
    <TextView />   /* what goes inside my control's linear layout */
</MyfancyLayout>

您将如何处理?我想避免重写整个线性布局onMeasure/onLayout方法.这是我目前所拥有的:

How would you approach this? I'd like to avoid re-writing the whole linear layout onMeasure / onLayout methods. This is what I have for the moment:

/* 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)?

How would you go about inserting the user-specified content (the TextView in main.xml) in the right place (id=container)?

干杯!

罗曼

-----编辑-------

----- edit -------

在这方面仍然不走运,所以我更改了设计以使用更简单的布局,并决定使用一些重复的XML.仍然对任何人都非常感兴趣,但是知道该怎么做!

Still no luck on this, so I changed my design to use a simpler layout and decided to live with a bit of repeated XML. Still very interested in anyone knows how to do this though!

推荐答案

这个确切的问题已经困扰了我一段时间,但直到现在我已经解决了.

This exact question bugged me for some time already but it's only now that I've solved it.

乍看之下,问题在于这样一个事实,即声明性内容(在您的情况下为TextView)是在 ctor之后(我们通常会夸大布局)的某个时间实例化的,所以它也是早期,手头有声明性内容和模板内容,可以将前者推入后者.

From a first glance, the problem lies in the fact that a declarative content (TextView in Your case) is instantiated sometime after ctor (where we're usually inflating our layouts), so it's too early have both declarative and template content at hand to push the former inside the latter.

我找到了一个可以同时操作两者的地方:这是一个onFinishInflate()方法.这是我的情况:

I've found one such place where we can manipulate the both: it's a onFinishInflate() method. Here's how it goes in my case:

    @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与以下内容没有什么不同:

A labeled_layout.xml referenced above is not unlike something like this:

<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>

现在(仍然省略一些细节)在其他地方,我们可能会像这样使用它:

Now (still omitting some details) elsewhere we might use it like this:

        <com.example.widget.LabeledLayout
            android:layout_width    ="fill_parent"
            android:layout_height   ="wrap_content">
            <!-- example content -->
        </com.example.widget.LabeledLayout> 

这篇关于带孩子的自定义Android控件的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆