我想在Android中创建一个包含一些逻辑的自定义复合控件。出于此示例的目的,假设我希望它在单击时在两个视图之间切换。
根据API guide,看起来这样做的方法是创建一个扩展Layout的新类,并在那里做所有事情。
所以我做到了这一点:
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:id="@+id/view1"
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:text="Hello"/>
<TextView
android:id="@+id/view2"
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:text="World"
android:visibility="gone"/>
</RelativeLayout>
然后我创建了我的自定义Layout类,并在其中添加了逻辑:
公共类MyWidget扩展RelativeLayout { public final查看mView1; public final查看mView2;
public MyWidget(Context context, AttributeSet attrs) {
super(context, attrs);
LayoutInflater inflater = (LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
RelativeLayout view = (RelativeLayout) inflater.inflate(R.layout.my_widget, this, true);
mView1 = view.findViewById(R.id.view1);
mView2 = view.findViewById(R.id.view2);
view.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
switchViews();
}
});
}
public void switchViews() {
if (mView1.getVisibility() == View.VISIBLE) {
mView1.setVisibility(View.GONE);
} else {
mView1.setVisibility(View.VISIBLE);
}
if (mView2.getVisibility() == View.VISIBLE) {
mView2.setVisibility(View.GONE);
} else {
mView2.setVisibility(View.VISIBLE);
}
}
}
最后,我将自定义视图包含在某个布局中:
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<com.example.MyWidget
android:layout_height="match_parent"
android:layout_width="match_parent"/>
</RelativeLayout
这很有效。
我对这个解决方案并不完全满意,原因有两个:
在MyWidget的构造函数中,我通过调用RelativeLayout
构造函数以及位于XML布局根目录的构造函数来实例化2个嵌套super()
。为此,我知道我可以使用<merge>
作为我的XML根,这可以让我摆脱额外的RelativeLayout
。除了定义XML属性(例如android:background
标签上的<merge>
没有任何效果,所以我必须以编程方式定义它,这不是很好。
自定义View是RelativeLayout的子类,因此公开它从中继承的方法,例如addView()
,即使向它添加子视图也没有意义。我知道我可以覆盖这些方法来阻止用户这样做,但我仍然觉得从View继承它会更清晰。