系统控件view有三个构造方法,分别如下
public DrawView(Context context) { super(context); } public DrawView(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); } public DrawView(Context context, AttributeSet attrs) { super(context, attrs); }
关于构造方法,网上给的解释是
如果在Code中实例化一个View会调用第一个构造函数,如果在xml中定义会调用第二个构造函数,而第三个函数系统是不调用的,要由 View(我们自定义的或系统预定义的View,如此处的CustomTextView和Button)显式调用,比如在这里我们在第二个构造函数中调用 了第三个构造函数,并将R.attr.CustomizeStyle传给了第三个参数。第三个参数的意义就如同它的名字所说的,是默认的Style,只是这里没有说清楚,这里的默认的Style是指它在当前Application或Activity所用的Theme中的默认Style。
至于只有一个参数的方法,我们主要是在new一个view的时候,会使用。它的那个参数是上下文环境。如
Button button = new Button(this);
至于两个参数跟三个参数的方法调用情况,网上有说是跟你在xml中是否使用了style有关。不过,我验证了下,无论有无style,都仅仅是调用两个参数的构造方法。验证如下
自定义style
package com.example.testcode; import android.content.Context; import android.graphics.Canvas; import android.util.AttributeSet; import android.util.Log; import android.view.View; public class DrawView extends View { public DrawView(Context context) { super(context); } public DrawView(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); } public DrawView(Context context, AttributeSet attrs) { super(context, attrs); } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { // TODO Auto-generated method stub //这两个方法必须有一个,否则会报错 //super.onMeasure(widthMeasureSpec, heightMeasureSpec); setMeasuredDimension(200, 200); } @Override protected void onLayout(boolean changed, int left, int top, int right, int bottom) { // TODO Auto-generated method stub Log.e("123", "change===" + changed + " left===" + left + " top===" + top + " right===" + right + " bottom===" + bottom); super.onLayout(changed, left, top, right, bottom); } @Override protected void onDraw(Canvas canvas) { // TODO Auto-generated method stub Log.e("123", "onDraw"); super.onDraw(canvas); } }
xml中的使用
1.当没有style的时候
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" tools:context="com.example.testcode.MainActivity" > <com.example.testcode.DrawView android:layout_width="100dp" android:layout_height="100dp" /> </RelativeLayout>
打印结果
09-29 11:28:13.445: E/123(6555): drawview_2
2.当有style的时候
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" tools:context="com.example.testcode.MainActivity" > <com.example.testcode.DrawView style="@style/test" /> </RelativeLayout>
style
<style name="test"> <item name="android:layout_width">100dp</item> <item name="android:layout_height">100dp</item> <item name="android:background">#ff0000</item> </style>
打印结果
09-29 11:28:13.445: E/123(6555): drawview_2
所以,xml中的控件,只调用两个参数的方法。而三个参数的方法,其实是在二个参数的方法中显式调用的。我们可以看下Button源码
public class Button extends TextView { public Button(Context context) { this(context, null); } public Button(Context context, AttributeSet attrs) { this(context, attrs, com.android.internal.R.attr.buttonStyle); } public Button(Context context, AttributeSet attrs, int defStyleAttr) { this(context, attrs, defStyleAttr, 0); } public Button(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) { super(context, attrs, defStyleAttr, defStyleRes); } @Override public void onInitializeAccessibilityEvent(AccessibilityEvent event) { super.onInitializeAccessibilityEvent(event); event.setClassName(Button.class.getName()); } @Override public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) { super.onInitializeAccessibilityNodeInfo(info); info.setClassName(Button.class.getName()); } }
从上面我们很清除的看到了这几个构造方法的调用关系
1.1参数->2参数(没有传入属性)->3参数(传入了系统默认的style)->4参数