Android - 编写自定义(复合)组件

2022-08-31 08:16:59

我目前正在开发的Android应用程序的主要活动已经变得相当大。这主要是因为它包含一个带有3个选项卡的选项卡。每个选项卡都有相当多的组件。活动必须同时控制所有这些组件。因此,我认为您可以想象此活动有大约20个字段(几乎每个组件的字段)。此外,它还包含许多逻辑(单击侦听器,填充列表的逻辑等)。TabWidget

在基于组件的框架中,我通常做的是将所有内容拆分为自定义组件。然后,每个自定义组件都将具有明确的职责。它将包含自己的组件集以及与该组件相关的所有其他逻辑。

我试图弄清楚如何做到这一点,我在Android文档中发现了一些他们喜欢称之为“复合控件”的东西。(请参阅 http://developer.android.com/guide/topics/ui/custom-components.html#compound 并滚动到“复合控件”部分)我想基于定义视图结构的XML文件创建这样一个组件。

在文档中,它说:

请注意,与活动一样,您可以使用声明性(基于 XML)方法来创建包含的组件,也可以从代码中以编程方式嵌套它们。

好吧,这是个好消息!基于 XML 的方法正是我想要的!但它没有说如何做,除了它“像一个活动”......但是我在活动中所做的是调用从 XML 膨胀视图。例如,如果子类 .)该方法不可用。setContentView(...)LinearLayout

所以我尝试像这样手动膨胀XML:

public class MyCompoundComponent extends LinearLayout {

    public MyCompoundComponent(Context context, AttributeSet attributeSet) {
        super(context, attributeSet);
        LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        inflater.inflate(R.layout.my_layout, this);
    }
}

这有效,除了我正在加载的 XML 已声明为根元素。这导致膨胀是一个孩子,其本身已经是一个!!所以现在我们有一个冗余的线性布局和它实际需要的视图。LinearLayoutLinearLayoutMyCompoundComponentLinearLayoutMyCompoundComponent

有人可以为我提供更好的方法来解决这个问题,避免冗余实例化吗?LinearLayout


答案 1

使用合并标记作为 XML 根目录

<merge xmlns:android="http://schemas.android.com/apk/res/android">
<!-- Your Layout -->
</merge>

查看此文章。


答案 2

我认为你应该这样做的方法是使用你的类名作为XML根元素:

<com.example.views.MyView xmlns:....
       android:orientation="vertical" etc.>
    <TextView android:id="@+id/text" ... />
</com.example.views.MyView>

然后从要使用的任何布局派生类。请注意,如果您使用的是此方法,则此处不使用布局膨胀器。

public class MyView extends LinearLayout
{
    public ConversationListItem(Context context, AttributeSet attrs)
    {
        super(context, attrs);
    }
    public ConversationListItem(Context context, AttributeSet attrs, int defStyle)
    {
        super(context, attrs, defStyle);
    }


    public void setData(String text)
    {
        mTextView.setText(text);
    }

    private TextView mTextView;

    @Override
    protected void onFinishInflate()
    {
        super.onFinishInflate();

        mTextView = (TextView)findViewById(R.id.text);
    }
}

然后,您可以像往常一样在 XML 布局中使用视图。如果要以编程方式创建视图,则必须自行膨胀:

MyView v = (MyView)inflater.inflate(R.layout.my_view, parent, false);

不幸的是,这不允许您这样做,因为似乎没有解决嵌套布局问题的方法,因此这并不是一个真正的完整解决方案。你可以添加一个像这样的方法来使它变得更好一些:v = new MyView(context)MyView

public static MyView create(Context context)
{
    return (MyView)LayoutInflater.fromContext(context).inflate(R.layout.my_view, null, false);
}

免责声明:我可能在谈论完全的波洛克。


推荐