我想在 Android 中创建一个包含一些逻辑的自定义复合控件。出于本示例的目的,假设我希望它在单击时在两个视图之间切换。
根据API 指南,看起来这样做的方法是创建一个扩展 Layout 的新类,并在其中完成所有操作。
所以我这样做了:
- 我创建了一个 XML 布局来为我的自定义组件进行扩展:
.
<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 View mView1; 公共最终视图 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
通过调用super()
构造函数来实例化嵌套的 2,以及位于我的 XML 布局根目录中的那个。为此,我知道我可以改为使用<merge>
我的 XML 根,这让我摆脱了额外的RelativeLayout
.android:background
除了在我的标签上定义 XML 属性<merge>
没有任何效果,所以我必须以编程方式定义它,这不是很好。自定义 View 是 RelativeLayout 的子类,因此会公开它继承自它的方法,例如
addView()
,即使向其添加子视图没有意义。我知道我可以重写这些方法来阻止用户这样做,但我仍然会发现从 View 继承更干净。