代码之家  ›  专栏  ›  技术社区  ›  Tom van Zummeren

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

  •  130
  • Tom van Zummeren  · 技术社区  · 16 年前

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

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

    我试图弄明白这是怎么做到的,我在Android文档中找到了他们喜欢称之为“复合控件”的东西。(见 http://developer.android.com/guide/topics/ui/custom-components.html#compound 并滚动到“复合控件”部分)我想基于定义视图结构的XML文件创建这样的组件。

    文件上写着:

    注意,就像活动一样, 您可以使用声明性 (基于XML)创建 包含的组件,或者可以嵌套 它们是以编程方式从代码中获取的。

    好吧,这是好消息!基于XML的方法正是我想要的!但它并没有说明如何去做,只是说它“就像一个活动”…但我在活动中所做的是呼叫 setContentView(...) 从XML膨胀视图。例如,如果子类 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 线性布局 声明为根元素。这导致膨胀 线性布局 是的孩子 MyCompoundComponent 它本身就是一个 线性布局 !!所以现在我们之间有一个多余的线性布局 mycompoundcomponent公司 以及它实际需要的视图。

    有人能给我提供一个更好的方法来解决这个问题,避免多余的 线性布局 实例化?

    2 回复  |  直到 13 年前
        1
  •  99
  •   bhatt4982    16 年前

    使用 合并 标记为XML根

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

    Check this article.

        2
  •  0
  •   Timmmm    13 年前

    我认为您应该这样做,即使用类名作为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);
    }
    

    免责声明:我可能在胡说八道。