Android - 编写自定义(复合)组件
我目前正在开发的 Android 应用程序的主要活动已经变得相当大。这主要是因为它包含一个带有 3 个选项卡的 TabWidget
。每个选项卡都有相当多的组件。该活动必须立即控制所有这些组件。所以我想你可以想象这个 Activity 有大约 20 个字段(几乎每个组件都有一个字段)。它还包含很多逻辑(点击监听器、填充列表的逻辑等)。
我通常在基于组件的框架中所做的是将所有内容拆分为自定义组件。每个自定义组件都会有明确的职责。它将包含它自己的一组组件以及与该组件相关的所有其他逻辑。
我试图弄清楚如何做到这一点,并在 Android 文档中找到了一些东西,他们喜欢称之为“复合控件”。 (请参阅http://developer.android.com/guide/topics /ui/custom-components.html#compound 并滚动到“复合控件”部分)我想基于定义视图结构的 XML 文件创建这样的组件。
在文档中它说:
请注意,就像 Activity 一样, 你可以使用声明式 (基于 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 已将 LinearLayout
声明为根元素。这导致膨胀的 LinearLayout
成为 MyCompoundComponent
的子级,而它本身已经是一个 LinearLayout
!所以现在我们在 MyCompoundComponent 和它实际需要的视图之间有一个冗余的 LinearLayout。
有人可以为我提供一种更好的方法来解决这个问题,避免实例化冗余的 LinearLayout 吗?
The Android app I'm currently developing has a main activity that has grown quite large. This is mainly because it contains a TabWidget
with 3 tabs. Each tab has quite a few components. The activity has to control of all those components at once. So I think you can imagine that this Activity has like 20 fields (a field for almost every component). Also it contains a lot of logic (click listeners, logic to fill lists, etc).
What I normally do in component based frameworks is to split everything up into custom components. Each custom component would then have a clear responsibility. It would contain it's own set of components and all other logic related to that component.
I tried to figure out how this can be done, and I found something in the Android documentation what they like to call a "Compound Control". (See http://developer.android.com/guide/topics/ui/custom-components.html#compound and scroll to the "Compound Controls" section) I would like to create such a component based on an XML file defining the view structure.
In the documentation it says:
Note that just like with an Activity,
you can use either the declarative
(XML-based) approach to creating the
contained components, or you can nest
them programmatically from your code.
Well, that's good news! The XML-based approach is exactly what I want! But it doesn't say how to do it, except that it is "like with an Activity"... But what I do in an Activity is call setContentView(...)
to inflate the views from XML. That method is not available if you for example subclass LinearLayout
.
So I tried to inflate the XML manually like this:
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);
}
}
This works, except for the fact that the XML I'm loading has LinearLayout
declared as the root element. This results in the inflated LinearLayout
being a child of MyCompoundComponent
which itself already is a LinearLayout
!! So now we have a redundant LinearLayout in between MyCompoundComponent
and the views it actually needs.
Can somebody please provide me with a better way to approach this, avoiding having a redundant LinearLayout
instantiated?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
使用merge标签作为您的XML根
查看这篇文章。
Use merge tag as your XML root
Check this article.
我认为您应该这样做的方法是使用您的类名作为 XML 根元素:
然后让您的类从您想要使用的任何布局派生。请注意,如果您使用此方法,则您不会在此处使用布局膨胀器。
然后您可以像平常一样在 XML 布局中使用视图。如果你想以编程方式创建视图,你必须自己膨胀它:
不幸的是,这不允许你这样做
v = new MyView(context)
因为似乎没有办法绕过嵌套布局问题,所以这并不是一个完整的解决方案。您可以将这样的方法添加到MyView
中,使其变得更好一点:免责声明:我可能完全是胡说八道。
I think the way you're supposed to do it, is use your class name as the XML root element:
And then have your class derived from whichever layout you want to use. Note that if you are using this method you don't use the layout inflater here.
And then you can use your view in XML layouts as normal. If you want to make the view programmatically you have to inflate it yourself:
Unfortunately this doesn't let you do
v = new MyView(context)
because there doesn't seem to be a way around the nested layouts problem, so this isn't really a full solution. You could add a method like this toMyView
to make it a bit nicer:Disclaimer: I may be talking complete bollocks.