Mic*_*ine 136 android android-custom-view
在创建自定义视图时,我注意到许多人似乎这样做:
public MyView(Context context) {
super(context);
// this constructor used when programmatically creating view
doAdditionalConstructorWork();
}
public MyView(Context context, AttributeSet attrs) {
super(context, attrs);
// this constructor used when creating view through XML
doAdditionalConstructorWork();
}
private void doAdditionalConstructorWork() {
// init variables etc.
}
Run Code Online (Sandbox Code Playgroud)
我的第一个问题是,构造函数MyView(Context context, AttributeSet attrs, int defStyle)怎么样?我不确定它在哪里使用,但我在超级课程中看到它.我需要它,它在哪里使用?
Ovi*_*tcu 141
如果您还要添加自定义View,xml例如:
<com.mypack.MyView
...
/>
Run Code Online (Sandbox Code Playgroud)
你将需要构造函数public MyView(Context context, AttributeSet attrs),否则你会得到一个ExceptionAndroid尝试膨胀你的View.
如果您添加Viewfrom xml并指定android:style属性,例如:
<com.mypack.MyView
style="@styles/MyCustomStyle"
...
/>
Run Code Online (Sandbox Code Playgroud)
MyCustomStyle在应用显式XML属性之前,还将调用第二个构造函数并默认样式.
当您希望应用程序中的所有视图具有相同的样式时,通常会使用第三个构造函数.
Jin*_*Jin 112
如果覆盖所有三个构造函数,请不要进行CASCADE this(...)CALLS.你应该这样做:
public MyView(Context context) {
super(context);
init(context, null, 0);
}
public MyView(Context context, AttributeSet attrs) {
super(context,attrs);
init(context, attrs, 0);
}
public MyView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
init(context, attrs, defStyle);
}
private void init(Context context, AttributeSet attrs, int defStyle) {
// do additional work
}
Run Code Online (Sandbox Code Playgroud)
原因是父类可能在其自己的构造函数中包含您可能意外覆盖的默认属性.例如,这是以下构造函数TextView:
public TextView(Context context) {
this(context, null);
}
public TextView(Context context, @Nullable AttributeSet attrs) {
this(context, attrs, com.android.internal.R.attr.textViewStyle);
}
public TextView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
this(context, attrs, defStyleAttr, 0);
}
Run Code Online (Sandbox Code Playgroud)
如果你没有打电话super(context),你就不会正确设置R.attr.textViewStyle为样式attr.
mbo*_*nin 45
以编程方式实例化视图时使用.
用于LayoutInflater应用xml属性.如果命名了此属性之一,则style在布局xml文件中查找显式值之前,将查找属性的属性.
假设您要将默认样式应用于所有窗口小部件,而无需style在每个布局文件中指定.例如,默认情况下使所有复选框变为粉红色.您可以使用defStyleAttr执行此操作,框架将在主题中查找默认样式.
请注意,前一段时间defStyleAttr命名错误,defStyle并且有关于是否真的需要此构造函数的讨论.请参阅https://code.google.com/p/android/issues/detail?id=12683
如果您可以控制应用程序的基本主题,则第3个构造函数可以正常工作.这适用于谷歌,因为他们将他们的小部件与默认主题一起发送.但是假设您正在编写一个小部件库,并且您希望设置默认样式而无需用户调整其主题.您现在可以defStyleRes通过将它设置为2个第一个构造函数中的默认值来执行此操作:
public MyView(Context context) {
super(context, null, 0, R.style.MyViewStyle);
init();
}
public MyView(Context context, AttributeSet attrs) {
super(context, attrs, 0, R.style.MyViewStyle);
init();
}
Run Code Online (Sandbox Code Playgroud)
如果您正在实现自己的视图,则只需要2个第一个构造函数,并且可以由框架调用.
如果希望视图是可扩展的,则可以为类的子级实现第4个构造函数,以便能够使用全局样式.
我没有看到第3个构造函数的真实用例.如果您没有为窗口小部件提供默认样式但仍希望用户能够这样做,则可能是快捷方式.不应该发生那么多.
Kotlin似乎减轻了许多痛苦:
class MyView
@JvmOverloads constructor(context: Context, attrs: AttributeSet? = null, defStyle: Int = 0)
: View(context, attrs, defStyle)
Run Code Online (Sandbox Code Playgroud)
@JvmOverloads将生成所有必需的构造函数(请参见该注释的文档),每个构造函数都可能调用super()。然后,只需将您的初始化方法替换为Kotlin init {}块。样板代码不见了!
| 归档时间: |
|
| 查看次数: |
31462 次 |
| 最近记录: |