xml中控件调用构造方法

系统控件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参数

原文地址:https://www.cnblogs.com/zhangshuli-1989/p/vz_constructor_15910161.html