由多个视图组成的自定义视图

25

我有一组视图,我想永远一起使用。 例如:

<LinearLayout>
    <TextView />
    <EditView />
</LinearLayout>

文本视图是提示,编辑视图是答案。我想给这个组合起一个名字,并能够使用该名称将其插入到XML中。 我希望它成为自定义视图,以便我可以将其放置在类中并为其创建各种实用函数。 有没有办法做到这一点? 我知道我可以子类化LinearLayout并在Java代码中动态创建子项,但那使我失去了通过XML轻松进行更改的能力。 有更好的方法吗?

是的,我也有其他需要比仅仅是提示的地方要这样做。


无耻的自我推销,但可能与此相关 - http://stackoverflow.com/questions/11722340/edittext-on-demand-widget - Shark
你有没有读过Android关于设计自定义组件的文章? - Sam
是的,我有Sam,并且我之前自己编写了3个自定义视图(一个相机视图用于显示相机,一个UrlImageView用于直接从Web下载图像到ImageView,以及一个DragAndDrop图像布局在AbsoluteLayout上方)。但是那个页面上的所有内容都没有向您展示如何在xml中定义具有子视图的小部件-它们都是在Java中完成的。我希望避免这种情况。 - Gabe Sechan
3个回答

56

这个例子是关于水平数字选择器小部件的,但其核心概念相同。

首先,为您的自定义组件创建XML布局。

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="horizontal" >

   <Button
       android:id="@+id/btn_minus"
       android:layout_width="50dp"
       android:layout_height="wrap_content"
       android:text="-" />

   <EditText
       android:id="@+id/edit_text"
       android:layout_width="75dp"
       android:layout_height="wrap_content"
       android:inputType="number"
       android:gravity="center"
       android:focusable="false"
       android:text="0" />

   <Button
       android:id="@+id/btn_plus"
       android:layout_width="50dp"
       android:layout_height="wrap_content"
       android:text="+" />
</LinearLayout>

接下来创建Java类

public class HorizontalNumberPicker extends LinearLayout {
    public HorizontalNumberPicker(Context context, AttributeSet attrs) {
         super(context, attrs);
         LayoutInflater inflater = LayoutInflater.from(context);
         inflater.inflate(R.layout.horizontal_number_picker, this);
     }
 }

在 Java 类中添加所需的逻辑,然后您只需要像这样在 XML 布局中包含自定义组件:

<com.example.HorizontalNumberPicker
     android:id ="@+id/horizontal_number_picker"
     android:layout_width ="wrap_content"
     android:layout_height ="wrap_content" />


查看此链接以获取更多信息:http://developer.android.com/guide/topics/ui/custom-components.html#compound


我尝试了这个,先让Android Studio将其转换为Kotlin。在构造函数中,我使用了“this”来表示上下文,但是我对AttributeSet一无所知。我正在学习Android(来自iOS开发者背景)。 - Scooter
3
如果我理解正确的话,HorizontalNumberPicker 有两个 LinearLayouts?一个是它本身,另一个在构造函数中被填充。看起来多余了。 - rozina
1
@rozina 我认为你可以在自定义组件的布局文件中使用<merge>标签来代替LinearLayout。这样可以消除额外的布局。 - starkej2

4
使用复合控件来实现此目的。有很多关于它的示例和教程。祝好运 :)

1
将该XML放入布局XML文件中,并在需要时使用充气器膨胀视图。
LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View rowView = inflater.inflate(R.layout.some_id, parent, false);

一旦您拥有了视图,您可以编写一个实用程序类来接受此视图并对其执行操作。使用findViewById()检索文本和编辑视图,或使用ViewHolder模式存储对其他视图的引用。


嗯。如果我在从布局(比如LinearLayout)派生的类的构造函数中执行此操作,我可以在父xml中引用它,并将其作为父级传递。如果子视图的顶层xml是合并标记,它将消除我们否则需要塞入其中的额外布局。我还可以使用ViewHolder模式来提高效率,但是持有者本身是一个View,因此我可以避免做所有丑陋的标记。我认为这很有潜力,我会在今天晚些时候回家后测试它。 - Gabe Sechan

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接