视图有 3 个构造函数:
SurfaceView(Context context)
SurfaceView(Context context, AttributeSet attrs)
SurfaceView(Context context, AttributeSet attrs, int defStyle)
注意:第三种样式是在 API 级别 11 中添加的。但是如果您想为较新版本的 API 创建自定义视图,您应该实现它。
在实现自定义视图时,如果您希望它被广泛使用,那么您应该实现三个构造函数 - 因为您的视图在代码的不同部分中的另一种用途或另一个应用程序可以使用任何构造函数实例化它。
如果您以编程方式构建视图,那么您可以决定使用哪个构造函数。
但是,当从 XML 引用它们时,Android 框架会实例化您的视图。
<com.me.Common.MyView
android:layout_width="wrap_contents"
...
/>
等等
这些实例化视图的 XML 声明可以包含许多属性,其中一些是“android:”命名空间中的标准 android 属性。如果您将这些传递给您正在扩展的 SuperClass(如果您正在扩展 View 类 - 就像您一样),那么它将解析并使用它们,您不需要做太多事情。
但是你也可以在自己的名字name中定义和使用自定义属性
<com.me.Common.MyView
android:layout_width="wrap_contents"
...
com.me:num_elements="10"
/>
然后您应该解析在构造函数中传递的属性集并更改 View 对象的行为以尊重 XML 中的设置。“android:”属性将被超类解析和使用。
因此,由于您不确切知道 Android 框架将如何实例化您的自定义视图(这将取决于声明它的 XML 标记),您应该实现三个构造函数。
注意:使用标准 Java 覆盖样式并让每个构造函数通过 super 使用更复杂的样式是很诱人的:
MyView(Context context, AttributeSet attrs) {
super(context, attrs, 0);
}
但是我已经看到这会导致问题,因为 0 并不总是有效的样式。因此,我建议您实现一个执行您自己的客户代码的 init() 方法,并调用与框架用于您的客户视图的构造函数的参数相对应的超类的构造函数:
public AnimationController(Context context) {
super(context);
initUI(context, null, -1);
}
public AnimationController(Context context, AttributeSet attrs) {
super(context, attrs);
initUI(context, attrs, -1);
}
public AnimationController(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
initUI(context, attrs, defStyle);
}
尤其是具有三个参数的 super() 在 API < 11 的设备上可能不存在。
以这种方式实现自定义视图使它们更具可配置性和可重用性,因为您可以将它们布置在具有不同属性集的不同 XML 文件中,或者使用定义一组属性的样式 - 就像使用 Android 视图一样。