Java Android - 编写自定义(复合)组件
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/1476371/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Android - Writing a custom (compound) component
提问by Tom van Zummeren
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).
我目前正在开发的 Android 应用程序的主要活动已经变得相当大。这主要是因为它包含一个TabWidget
带有 3 个选项卡的选项卡。每个选项卡都有相当多的组件。活动必须同时控制所有这些组件。所以我想你可以想象这个 Activity 有大约 20 个字段(几乎每个组件都有一个字段)。它还包含很多逻辑(单击侦听器、填充列表的逻辑等)。
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#compoundand scroll to the "Compound Controls" section) I would like to create such a component based on an XML file defining the view structure.
我试图弄清楚如何做到这一点,我在 Android 文档中找到了他们喜欢称之为“复合控制”的东西。(请参阅http://developer.android.com/guide/topics/ui/custom-components.html#compound并滚动到“复合控件”部分)我想基于定义了视图结构。
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.
请注意,就像使用 Activity 一样,您可以使用声明式(基于 XML 的)方法来创建包含的组件,也可以从代码中以编程方式嵌套它们。
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
.
嗯,这是个好消息!基于 XML 的方法正是我想要的!但它没有说明如何做到这一点,只是它“就像一个活动”......但我在活动中所做的是调用setContentView(...)
以从 XML 膨胀视图。例如,如果您使用 subclass ,则该方法不可用LinearLayout
。
So I tried to inflate the XML manually like this:
所以我尝试像这样手动膨胀 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);
}
}
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.
这有效,除了我正在加载的 XML 已LinearLayout
声明为根元素的事实。这导致膨胀LinearLayout
成为一个MyCompoundComponent
本身已经是一个孩子的孩子LinearLayout
!!所以现在我们在中间有一个冗余的 LinearLayoutMyCompoundComponent
和它实际需要的视图。
Can somebody please provide me with a better way to approach this, avoiding having a redundant LinearLayout
instantiated?
有人可以为我提供一种更好的方法来解决这个问题,避免冗余LinearLayout
实例化吗?
采纳答案by bhatt4982
Use mergetag as your XML root
使用合并标签作为您的 XML 根
<merge xmlns:android="http://schemas.android.com/apk/res/android">
<!-- Your Layout -->
</merge>
回答by Timmmm
I think the way you're supposed to do it, is use your class name as the XML root element:
我认为你应该这样做的方式是使用你的类名作为 XML 根元素:
<com.example.views.MyView xmlns:....
android:orientation="vertical" etc.>
<TextView android:id="@+id/text" ... />
</com.example.views.MyView>
And then have your class derived from whichever layout you want to use. Note that if you are using this method you don'tuse the layout inflater here.
然后让您的类从您要使用的任何布局派生。请注意,如果您使用此方法,则不要在此处使用布局充气器。
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);
}
}
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:
然后您可以照常在 XML 布局中使用您的视图。如果你想以编程方式制作视图,你必须自己膨胀它:
MyView v = (MyView)inflater.inflate(R.layout.my_view, parent, false);
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 to MyView
to make it a bit nicer:
不幸的是,这不会让您这样做,v = new MyView(context)
因为似乎没有办法解决嵌套布局问题,所以这并不是真正的完整解决方案。你可以添加一个这样的方法MyView
来使它更好一点:
public static MyView create(Context context)
{
return (MyView)LayoutInflater.fromContext(context).inflate(R.layout.my_view, null, false);
}
Disclaimer: I may be talking complete bollocks.
免责声明:我可能说的是完全胡说八道。