自定义View时,构造参数的调用


初始Custom View的构造函数

之前写过一篇实现圆形进度条的博客(自定义圆形进度条),通常我们在实现Custom View的时候,都会先继承View并实现View的三个构造函数,例如:

<code class="language-java hljs  has-numbering"><span class="hljs-keyword">import</span> android.content.Context;
<span class="hljs-keyword">import</span> android.graphics.Canvas;
<span class="hljs-keyword">import</span> android.util.AttributeSet;
<span class="hljs-keyword">import</span> android.view.View;

<span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">MyCustomView</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">View</span> {</span>
    <span class="hljs-javadoc">/**
     * 第一个构造函数
     */</span>
    <span class="hljs-keyword">public</span> <span class="hljs-title">MyCustomView</span>(Context context) {
        <span class="hljs-keyword">this</span>(context, <span class="hljs-keyword">null</span>);
    }

    <span class="hljs-javadoc">/**
     * 第二个构造函数
     */</span>
    <span class="hljs-keyword">public</span> <span class="hljs-title">MyCustomView</span>(Context context, AttributeSet attrs) {
        <span class="hljs-keyword">this</span>(context, attrs, <span class="hljs-number">0</span>);
    }

    <span class="hljs-javadoc">/**
     * 第三个构造函数
     */</span>
    <span class="hljs-keyword">public</span> <span class="hljs-title">MyCustomView</span>(Context context, AttributeSet attrs, <span class="hljs-keyword">int</span> defStyle) {
        <span class="hljs-keyword">super</span>(context, attrs, defStyle);
        <span class="hljs-comment">// TODO:获取自定义属性</span>
    }

    <span class="hljs-annotation">@Override</span>
    <span class="hljs-keyword">protected</span> <span class="hljs-keyword">void</span> <span class="hljs-title">onDraw</span>(Canvas canvas) {
        <span class="hljs-keyword">super</span>.onDraw(canvas);
    }
}</code><ul class="pre-numbering" style=""><li>1</li><li>2</li><li>3</li><li>4</li><li>5</li><li>6</li><li>7</li><li>8</li><li>9</li><li>10</li><li>11</li><li>12</li><li>13</li><li>14</li><li>15</li><li>16</li><li>17</li><li>18</li><li>19</li><li>20</li><li>21</li><li>22</li><li>23</li><li>24</li><li>25</li><li>26</li><li>27</li><li>28</li><li>29</li><li>30</li><li>31</li><li>32</li><li>33</li></ul><ul class="pre-numbering" style=""><li>1</li><li>2</li><li>3</li><li>4</li><li>5</li><li>6</li><li>7</li><li>8</li><li>9</li><li>10</li><li>11</li><li>12</li><li>13</li><li>14</li><li>15</li><li>16</li><li>17</li><li>18</li><li>19</li><li>20</li><li>21</li><li>22</li><li>23</li><li>24</li><li>25</li><li>26</li><li>27</li><li>28</li><li>29</li><li>30</li><li>31</li><li>32</li><li>33</li></ul>

网上有很多关于三个构造函数使用时机的说法,但是说法正确的却没有几家,这里正式的给大家科普一下:

  1. 在代码中直接new一个Custom View实例的时候,会调用第一个构造函数.这个没有任何争议.
  2. 在xml布局文件中调用Custom View的时候,会调用第二个构造函数.这个也没有争议.
  3. 在xml布局文件中调用Custom View,并且Custom View标签中还有自定义属性时,这里调用的还是第二个构造函数.

也就是说,系统默认只会调用Custom View的前两个构造函数,至于第三个构造函数的调用,通常是我们自己在构造函数中主动调用的(例如,在第二个构造函数中调用第三个构造函数).

至于自定义属性的获取,通常是在构造函数中通过obtainStyledAttributes函数实现的.这里先介绍一下如何生成Custom View的自定义属性.


生成Custom View的自定义属性

Custom View添加自定义属性主要是通过declare-styleable标签为其配置自定义属性,具体做法是: 在res/values/目录下增加一个resources xml文件,示例如下(res/values/attrs_my_custom_view.xml):

<code class="language-xml hljs  has-numbering"><span class="hljs-tag"><<span class="hljs-title">resources</span>></span>
    <span class="hljs-tag"><<span class="hljs-title">declare-styleable</span> <span class="hljs-attribute">name</span>=<span class="hljs-value">"MyCustomView"</span>></span>
        <span class="hljs-tag"><<span class="hljs-title">attr</span> <span class="hljs-attribute">name</span>=<span class="hljs-value">"custom_attr1"</span> <span class="hljs-attribute">format</span>=<span class="hljs-value">"string"</span> /></span>
        <span class="hljs-tag"><<span class="hljs-title">attr</span> <span class="hljs-attribute">name</span>=<span class="hljs-value">"custom_attr2"</span> <span class="hljs-attribute">format</span>=<span class="hljs-value">"string"</span> /></span>
        <span class="hljs-tag"><<span class="hljs-title">attr</span> <span class="hljs-attribute">name</span>=<span class="hljs-value">"custom_attr3"</span> <span class="hljs-attribute">format</span>=<span class="hljs-value">"string"</span> /></span>
        <span class="hljs-tag"><<span class="hljs-title">attr</span> <span class="hljs-attribute">name</span>=<span class="hljs-value">"custom_attr4"</span> <span class="hljs-attribute">format</span>=<span class="hljs-value">"string"</span> /></span>
    <span class="hljs-tag"></<span class="hljs-title">declare-styleable</span>></span>
    <span class="hljs-tag"><<span class="hljs-title">attr</span> <span class="hljs-attribute">name</span>=<span class="hljs-value">"custom_attr5"</span> <span class="hljs-attribute">format</span>=<span class="hljs-value">"string"</span> /></span>
<span class="hljs-tag"></<span class="hljs-title">resources</span></span></code><ul class="pre-numbering" style=""><li>1</li><li>2</li><li>3</li><li>4</li><li>5</li><li>6</li><li>7</li><li>8</li><li>9</li></ul><ul class="pre-numbering" style=""><li>1</li><li>2</li><li>3</li><li>4</li><li>5</li><li>6</li><li>7</li><li>8</li><li>9</li></ul>

在上述xml文件中,我们声明了一个自定义属性集MyCustomView,其中包含了custom_attr1,custom_att2,custom_attr3,custom_attr4四个属性.同时,我们还声明了一个独立的属性custom_attr5.

所有resources文件中声明的属性都会在R.attr类中生成对应的成员变量:

<code class="language-java hljs  has-numbering"><span class="hljs-keyword">public</span> <span class="hljs-keyword">final</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">R</span> {</span>
    <span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">final</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">attr</span> {</span>
        <span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">final</span> <span class="hljs-keyword">int</span> custom_attr1=<span class="hljs-number">0x7f010038</span>;
        <span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">final</span> <span class="hljs-keyword">int</span> custom_attr2=<span class="hljs-number">0x7f010039</span>;
        <span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">final</span> <span class="hljs-keyword">int</span> custom_attr3=<span class="hljs-number">0x7f01003a</span>;
        <span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">final</span> <span class="hljs-keyword">int</span> custom_attr4=<span class="hljs-number">0x7f01003b</span>;
        <span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">final</span> <span class="hljs-keyword">int</span> custom_attr5=<span class="hljs-number">0x7f010000</span>;
    }
}</code><ul class="pre-numbering" style=""><li>1</li><li>2</li><li>3</li><li>4</li><li>5</li><li>6</li><li>7</li><li>8</li><li>9</li></ul><ul class="pre-numbering" style=""><li>1</li><li>2</li><li>3</li><li>4</li><li>5</li><li>6</li><li>7</li><li>8</li><li>9</li></ul>

但是声明在标签中的属性,系统还会在R.styleable类中生成相关的成员变量:

<code class="language-java hljs  has-numbering"><span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">final</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">styleable</span> {</span>
        <span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">final</span> <span class="hljs-keyword">int</span>[] MyCustomView = {
            <span class="hljs-number">0x7f010038</span>, <span class="hljs-number">0x7f010039</span>, <span class="hljs-number">0x7f01003a</span>, <span class="hljs-number">0x7f01003b</span>
        };
        <span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">final</span> <span class="hljs-keyword">int</span> MyCustomView_custom_attr1 = <span class="hljs-number">0</span>;
        <span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">final</span> <span class="hljs-keyword">int</span> MyCustomView_custom_attr2 = <span class="hljs-number">1</span>;
        <span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">final</span> <span class="hljs-keyword">int</span> MyCustomView_custom_attr3 = <span class="hljs-number">2</span>;
        <span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">final</span> <span class="hljs-keyword">int</span> MyCustomView_custom_attr4 = <span class="hljs-number">3</span>;
}</code><ul class="pre-numbering" style=""><li>1</li><li>2</li><li>3</li><li>4</li><li>5</li><li>6</li><li>7</li><li>8</li><li>9</li></ul><ul class="pre-numbering" style=""><li>1</li><li>2</li><li>3</li><li>4</li><li>5</li><li>6</li><li>7</li><li>8</li><li>9</li></ul>

可以看出,R.styleable.MyCustomView是一个数组,其中的元素值恰好就是R.attr.custom_attr1~R.attr.custom_attr4的值.而下面的MyCustomView_custom_attr1~MyCustomView_custom_attr4正好就是其对应的索引.

知道了这些之后,我们就可以来学习一下,如何在Custom View的构造函数中获取自定义属性的值了.


在Custom View的构造函数中获取自定义属性

在第三个构造函数中获取自定义属性的代码如下:

<code class="language-java hljs  has-numbering"><span class="hljs-keyword">public</span> <span class="hljs-title">MyCustomView</span>(Context context, AttributeSet attrs, <span class="hljs-keyword">int</span> defStyleAttr) {
    <span class="hljs-keyword">super</span>(context, attrs, defStyleAttr);

    TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.MyCustomView);

    String attr1 = ta.getString(R.styleable.MyCustomView_custom_attr1);
    String attr2 = ta.getString(R.styleable.MyCustomView_custom_attr2);
    String attr3 = ta.getString(R.styleable.MyCustomView_custom_attr3);
    String attr4 = ta.getString(R.styleable.MyCustomView_custom_attr4);

    Log.e(<span class="hljs-string">"customview"</span>, <span class="hljs-string">"attr1="</span> + attr1);
    Log.e(<span class="hljs-string">"customview"</span>, <span class="hljs-string">"attr2="</span> + attr2);
    Log.e(<span class="hljs-string">"customview"</span>, <span class="hljs-string">"attr3="</span> + attr3);
    Log.e(<span class="hljs-string">"customview"</span>, <span class="hljs-string">"attr4="</span> + attr4);
    ta.recycle();
 }</code><ul class="pre-numbering" style=""><li>1</li><li>2</li><li>3</li><li>4</li><li>5</li><li>6</li><li>7</li><li>8</li><li>9</li><li>10</li><li>11</li><li>12</li><li>13</li><li>14</li><li>15</li><li>16</li></ul><ul class="pre-numbering" style=""><li>1</li><li>2</li><li>3</li><li>4</li><li>5</li><li>6</li><li>7</li><li>8</li><li>9</li><li>10</li><li>11</li><li>12</li><li>13</li><li>14</li><li>15</li><li>16</li></ul>

关于自定义属性的获取,我们主要是调用了context.obtainStyledAttributes这个函数,相信这个函数大家自定义View的时候都用的很熟练了.我们来看一下这个函数的源码实现:

<code class="language-java hljs  has-numbering"><span class="hljs-keyword">public</span> <span class="hljs-keyword">final</span> TypedArray <span class="hljs-title">obtainStyledAttributes</span>(AttributeSet set, @StyleableRes <span class="hljs-keyword">int</span>[] attrs) {
    <span class="hljs-keyword">return</span> getTheme().obtainStyledAttributes(set, attrs, <span class="hljs-number">0</span>, <span class="hljs-number">0</span>);
}</code><ul class="pre-numbering" style=""><li>1</li><li>2</li><li>3</li></ul><ul class="pre-numbering" style=""><li>1</li><li>2</li><li>3</li></ul>

通过对源码的追踪,我们发现context的两个参数的obtainStyledAttributes方法最终是调用了Theme的4个参数的obtainStyledAttributes方法.我们来看一下这个函数的源码实现:

<code class="language-java hljs  has-numbering"><span class="hljs-keyword">public</span> TypedArray <span class="hljs-title">obtainStyledAttributes</span>(AttributeSet set,
        @StyleableRes <span class="hljs-keyword">int</span>[] attrs, @AttrRes <span class="hljs-keyword">int</span> defStyleAttr, @StyleRes <span class="hljs-keyword">int</span> defStyleRes) {
    <span class="hljs-keyword">final</span> <span class="hljs-keyword">int</span> len = attrs.length;
    <span class="hljs-keyword">final</span> TypedArray array = TypedArray.obtain(Resources.<span class="hljs-keyword">this</span>, len);

    <span class="hljs-comment">// XXX note that for now we only work with compiled XML files.</span>
    <span class="hljs-comment">// To support generic XML files we will need to manually parse</span>
    <span class="hljs-comment">// out the attributes from the XML file (applying type information</span>
    <span class="hljs-comment">// contained in the resources and such).</span>
    <span class="hljs-keyword">final</span> XmlBlock.Parser parser = (XmlBlock.Parser)set;
    AssetManager.applyStyle(mTheme, defStyleAttr, defStyleRes,
            parser != <span class="hljs-keyword">null</span> ? parser.mParseState : <span class="hljs-number">0</span>, attrs, array.mData, array.mIndices);

    array.mTheme = <span class="hljs-keyword">this</span>;
    array.mXml = parser;

    <span class="hljs-keyword">if</span> (<span class="hljs-keyword">false</span>) {
        <span class="hljs-keyword">int</span>[] data = array.mData;

        System.out.println(<span class="hljs-string">"Attributes:"</span>);
        String s = <span class="hljs-string">"  Attrs:"</span>;
        <span class="hljs-keyword">int</span> i;
        <span class="hljs-keyword">for</span> (i=<span class="hljs-number">0</span>; i<set.getAttributeCount(); i++) {
            s = s + <span class="hljs-string">" "</span> + set.getAttributeName(i);
            <span class="hljs-keyword">int</span> id = set.getAttributeNameResource(i);
            <span class="hljs-keyword">if</span> (id != <span class="hljs-number">0</span>) {
                s = s + <span class="hljs-string">"(0x"</span> + Integer.toHexString(id) + <span class="hljs-string">")"</span>;
            }
            s = s + <span class="hljs-string">"="</span> + set.getAttributeValue(i);
        }
        System.out.println(s);
        s = <span class="hljs-string">"  Found:"</span>;
        TypedValue value = <span class="hljs-keyword">new</span> TypedValue();
        <span class="hljs-keyword">for</span> (i=<span class="hljs-number">0</span>; i<attrs.length; i++) {
            <span class="hljs-keyword">int</span> d = i*AssetManager.STYLE_NUM_ENTRIES;
            value.type = data[d+AssetManager.STYLE_TYPE];
            value.data = data[d+AssetManager.STYLE_DATA];
            value.assetCookie = data[d+AssetManager.STYLE_ASSET_COOKIE];
            value.resourceId = data[d+AssetManager.STYLE_RESOURCE_ID];
            s = s + <span class="hljs-string">" 0x"</span> + Integer.toHexString(attrs[i])
                + <span class="hljs-string">"="</span> + value;
        }
        System.out.println(s);
    }

    <span class="hljs-keyword">return</span> array;
}</code><ul class="pre-numbering" style=""><li>1</li><li>2</li><li>3</li><li>4</li><li>5</li><li>6</li><li>7</li><li>8</li><li>9</li><li>10</li><li>11</li><li>12</li><li>13</li><li>14</li><li>15</li><li>16</li><li>17</li><li>18</li><li>19</li><li>20</li><li>21</li><li>22</li><li>23</li><li>24</li><li>25</li><li>26</li><li>27</li><li>28</li><li>29</li><li>30</li><li>31</li><li>32</li><li>33</li><li>34</li><li>35</li><li>36</li><li>37</li><li>38</li><li>39</li><li>40</li><li>41</li><li>42</li><li>43</li><li>44</li><li>45</li><li>46</li><li>47</li></ul><ul class="pre-numbering" style=""><li>1</li><li>2</li><li>3</li><li>4</li><li>5</li><li>6</li><li>7</li><li>8</li><li>9</li><li>10</li><li>11</li><li>12</li><li>13</li><li>14</li><li>15</li><li>16</li><li>17</li><li>18</li><li>19</li><li>20</li><li>21</li><li>22</li><li>23</li><li>24</li><li>25</li><li>26</li><li>27</li><li>28</li><li>29</li><li>30</li><li>31</li><li>32</li><li>33</li><li>34</li><li>35</li><li>36</li><li>37</li><li>38</li><li>39</li><li>40</li><li>41</li><li>42</li><li>43</li><li>44</li><li>45</li><li>46</li><li>47</li></ul>

这里就不做过多的源码讲解,而是把这四个参数的含义解释给大家:

  1. AttributeSet set: 属性值的集合.
  2. int[] attrs: 我们自定义属性集合在R类中生成的int型数组.这个数组中包含了自定义属性的资源ID.
  3. int defStyleAttr: 这是当前Theme中的包含的一个指向style的引用.当我们没有给自定义View设置declare-styleable资源集合时,默认从这个集合里面查找布局文件中配置属性值.传入0表示不像该defStyleAttr中查找默认值.
  4. int defStyleRes: 这个也是一个指向Style的资源ID,但是仅在defStyleAttr为0或者defStyleAttr不为0但Theme中没有为defStyleAttr属性赋值时起作用.

由于一个属性可以在很多地方对其进行赋值,包括: XML布局文件中、decalare-styleable、theme中等,它们之间是有优先级次序的,按照优先级从高到低排序如下:

属性赋值优先级次序表:
在布局xml中直接定义 > 在布局xml中通过style定义 > 自定义View所在的Activity的Theme中指定style引用 > 构造函数中defStyleRes指定的默认值

为了让大家有更清楚更直观的了解,再接下来设置自定义属性的章节中,我将对custom_attr1~4这4个属性分别在上述四个地方进行定义,然后在Custom View的构造函数中获取它的值,从而看一下,优先级顺序是否和我们预期的一样.


设置自定义属性值

以下的第几个参数均是针对Resources.Theme类的obtainStyledAttributes四参数构造方法来说明的.


第二个参数——在布局xml文件中为属性赋值

在设置自定义属性之前,我们首先要在主Activity的布局文件中调用我们的Custom View,并且为其设置特定的属性.

主布局文件内容如下:

<code class="language-xml hljs  has-numbering"><span class="hljs-tag"><<span class="hljs-title">FrameLayout</span> <span class="hljs-attribute">xmlns:android</span>=<span class="hljs-value">"http://schemas.android.com/apk/res/android"</span>
    <span class="hljs-attribute">xmlns:custom</span>=<span class="hljs-value">"http://schemas.android.com/apk/res-auto"</span>
    <span class="hljs-attribute">android:id</span>=<span class="hljs-value">"@+id/container"</span>
    <span class="hljs-attribute">android:layout_width</span>=<span class="hljs-value">"match_parent"</span>
    <span class="hljs-attribute">android:layout_height</span>=<span class="hljs-value">"match_parent"</span>></span>

    <span class="hljs-tag"><<span class="hljs-title">com.kevintan.eventbussample.view.MyCustomView
</span>        <span class="hljs-attribute">android:id</span>=<span class="hljs-value">"@+id/id_custom_view"</span>
        <span class="hljs-attribute">android:layout_width</span>=<span class="hljs-value">"400dp"</span>
        <span class="hljs-attribute">android:layout_height</span>=<span class="hljs-value">"400dp"</span>
        <span class="hljs-attribute">custom:custom_attr1</span>=<span class="hljs-value">"attr1_xml"</span>
        <span class="hljs-attribute">style</span>=<span class="hljs-value">"@style/TestCustomView"</span>/></span>

<span class="hljs-tag"></<span class="hljs-title">FrameLayout</span>></span></code><ul class="pre-numbering" style=""><li>1</li><li>2</li><li>3</li><li>4</li><li>5</li><li>6</li><li>7</li><li>8</li><li>9</li><li>10</li><li>11</li><li>12</li><li>13</li><li>14</li></ul><ul class="pre-numbering" style=""><li>1</li><li>2</li><li>3</li><li>4</li><li>5</li><li>6</li><li>7</li><li>8</li><li>9</li><li>10</li><li>11</li><li>12</li><li>13</li><li>14</li></ul>

示例结果:

<code class="language-text hljs mathematica has-numbering"><span class="hljs-number">05</span>-<span class="hljs-number">28</span> <span class="hljs-number">17</span>:<span class="hljs-number">19</span>:<span class="hljs-number">56.542</span> <span class="hljs-number">23575</span>-<span class="hljs-number">23575</span>/? <span class="hljs-keyword">E</span>/customview: attr1=attr1_xml
<span class="hljs-number">05</span>-<span class="hljs-number">28</span> <span class="hljs-number">17</span>:<span class="hljs-number">19</span>:<span class="hljs-number">56.542</span> <span class="hljs-number">23575</span>-<span class="hljs-number">23575</span>/? <span class="hljs-keyword">E</span>/customview: attr2=null
<span class="hljs-number">05</span>-<span class="hljs-number">28</span> <span class="hljs-number">17</span>:<span class="hljs-number">19</span>:<span class="hljs-number">56.542</span> <span class="hljs-number">23575</span>-<span class="hljs-number">23575</span>/? <span class="hljs-keyword">E</span>/customview: attr3=null
<span class="hljs-number">05</span>-<span class="hljs-number">28</span> <span class="hljs-number">17</span>:<span class="hljs-number">19</span>:<span class="hljs-number">56.542</span> <span class="hljs-number">23575</span>-<span class="hljs-number">23575</span>/? <span class="hljs-keyword">E</span>/customview: attr4=null</code><ul class="pre-numbering" style=""><li>1</li><li>2</li><li>3</li><li>4</li></ul><ul class="pre-numbering" style=""><li>1</li><li>2</li><li>3</li><li>4</li></ul>

注意:

在给自定义属性赋值时,首先需要增加自定义属性的命名空间,例如: xmlns:custom=”http://schemas.Android.com/apk/res-auto”,Android Studio推荐使用res-auto,在Eclipse中需要使用Custom View所在的包名: xmlns:cv=”http://schemas.android.com/apk/com.kevintan.eventbussample.view”

这里,在布局文件中我们为custom_attr1赋值为: attr1_xml.自定义View中获取该属性值对应了getTheme().obtainStyledAttributes方法中的第二个参数@StyleableRes int[] attrs


第二个参数——在style中为属性赋值

其次,自定义属性还可以在Style中进行赋值.

首先,我们在xml布局文件中还为MyCustomView增加一个自定义的style,style代码如下:

<code class="language-xml hljs  has-numbering"><span class="hljs-tag"><<span class="hljs-title">style</span> <span class="hljs-attribute">name</span>=<span class="hljs-value">"TestCustomView"</span>></span><span class="css">
    <<span class="hljs-tag">item</span> <span class="hljs-tag">name</span>="<span class="hljs-tag">custom_attr1</span>"><span class="hljs-tag">attr1_style</span></<span class="hljs-tag">item</span>>
    <<span class="hljs-tag">item</span> <span class="hljs-tag">name</span>="<span class="hljs-tag">custom_attr2</span>"><span class="hljs-tag">attr2_style</span></<span class="hljs-tag">item</span>>
</span><span class="hljs-tag"></<span class="hljs-title">style</span>></span></code><ul class="pre-numbering" style=""><li>1</li><li>2</li><li>3</li><li>4</li></ul><ul class="pre-numbering" style=""><li>1</li><li>2</li><li>3</li><li>4</li></ul>

然后,我们修改布局文件,增加style字段:

<code class="language-xml hljs  has-numbering"><span class="hljs-tag"><<span class="hljs-title">FrameLayout</span> <span class="hljs-attribute">xmlns:android</span>=<span class="hljs-value">"http://schemas.android.com/apk/res/android"</span>
    <span class="hljs-attribute">xmlns:custom</span>=<span class="hljs-value">"http://schemas.android.com/apk/res-auto"</span>
    <span class="hljs-attribute">android:id</span>=<span class="hljs-value">"@+id/container"</span>
    <span class="hljs-attribute">android:layout_width</span>=<span class="hljs-value">"match_parent"</span>
    <span class="hljs-attribute">android:layout_height</span>=<span class="hljs-value">"match_parent"</span>></span>

    <span class="hljs-tag"><<span class="hljs-title">com.kevintan.eventbussample.view.MyCustomView
</span>        <span class="hljs-attribute">android:id</span>=<span class="hljs-value">"@+id/id_custom_view"</span>
        <span class="hljs-attribute">android:layout_width</span>=<span class="hljs-value">"400dp"</span>
        <span class="hljs-attribute">android:layout_height</span>=<span class="hljs-value">"400dp"</span>
        <span class="hljs-attribute">custom:custom_attr1</span>=<span class="hljs-value">"attr1_xml"</span>
        <span class="hljs-attribute">style</span>=<span class="hljs-value">"@style/TestCustomView"</span>/></span>

<span class="hljs-tag"></<span class="hljs-title">FrameLayout</span>></span></code><ul class="pre-numbering" style=""><li>1</li><li>2</li><li>3</li><li>4</li><li>5</li><li>6</li><li>7</li><li>8</li><li>9</li><li>10</li><li>11</li><li>12</li><li>13</li><li>14</li></ul><ul class="pre-numbering" style=""><li>1</li><li>2</li><li>3</li><li>4</li><li>5</li><li>6</li><li>7</li><li>8</li><li>9</li><li>10</li><li>11</li><li>12</li><li>13</li><li>14</li></ul>

示例结果:

<code class="language-text hljs mathematica has-numbering"><span class="hljs-number">05</span>-<span class="hljs-number">28</span> <span class="hljs-number">17</span>:<span class="hljs-number">19</span>:<span class="hljs-number">56.542</span> <span class="hljs-number">23575</span>-<span class="hljs-number">23575</span>/? <span class="hljs-keyword">E</span>/customview: attr1=attr1_xml
<span class="hljs-number">05</span>-<span class="hljs-number">28</span> <span class="hljs-number">17</span>:<span class="hljs-number">19</span>:<span class="hljs-number">56.542</span> <span class="hljs-number">23575</span>-<span class="hljs-number">23575</span>/? <span class="hljs-keyword">E</span>/customview: attr2=attr2_style
<span class="hljs-number">05</span>-<span class="hljs-number">28</span> <span class="hljs-number">17</span>:<span class="hljs-number">19</span>:<span class="hljs-number">56.542</span> <span class="hljs-number">23575</span>-<span class="hljs-number">23575</span>/? <span class="hljs-keyword">E</span>/customview: attr3=null
<span class="hljs-number">05</span>-<span class="hljs-number">28</span> <span class="hljs-number">17</span>:<span class="hljs-number">19</span>:<span class="hljs-number">56.542</span> <span class="hljs-number">23575</span>-<span class="hljs-number">23575</span>/? <span class="hljs-keyword">E</span>/customview: attr4=null</code><ul class="pre-numbering" style=""><li>1</li><li>2</li><li>3</li><li>4</li></ul><ul class="pre-numbering" style=""><li>1</li><li>2</li><li>3</li><li>4</li></ul>

这里我们再次对custom_attr1属性进行了赋值,同时我们对custom_attr2也进行了赋值.

小提示:
聪明的同学肯定都猜到我这样赋值的作用了,但是还是要简述一下:
对于custom_attr1,我们在xml布局文件、style、defStyle和theme中均进行赋值,那最终得到的结果必然能证实谁的优先级最高.
对于custom_attr2,我们在style、defStyle和theme中进行赋值,通过得到的结果我们能知道谁的优先级第二高.
对于custom_attr3和custom_attr4的赋值情况我就不多解释了,我相信大家都懂得!!

同时,还需要大家注意的是,只要是layout布局文件中,无论是通过namespace直接为属性赋值,还是通过style为属性赋值,在构造函数获取时都对应了getTheme().obtainStyledAttributes方法中的第二个参数@StyleableRes int[] attrs


第三个参数defStyleAttr

这个参数的意思是:

  • 原文: An attribute in the current theme that contains areference to a style resource that supplies defaults values for the TypedArray. Can be 0 to not look for defaults.
  • 翻译: 这是当前Theme中的包含的一个指向style的引用.当我们没有给自定义View设置declare-styleable资源集合时,默认从这个集合里面查找布局文件中配置属性值.传入0表示不向该defStyleAttr中查找默认值.

为了测试该参数的作用和优先级,我们需要进行如下操作.

首先, 我们先声明一个refrence格式的属性, 用于表示style的引用.声明在之前的res/values/attrs_my_custom_view.xml文件里即可:

<code class="language-xml hljs  has-numbering"><span class="hljs-tag"><<span class="hljs-title">attr</span> <span class="hljs-attribute">name</span>=<span class="hljs-value">"MyCustomViewDefStyleAttr"</span> <span class="hljs-attribute">format</span>=<span class="hljs-value">"reference"</span>/></span></code><ul class="pre-numbering" style=""><li>1</li></ul><ul class="pre-numbering" style=""><li>1</li></ul>

然后,需要到AndroidManifest.xml中查看包含该自定义View的Activity所使用的主题是:

<code class="hljs xml has-numbering"><span class="hljs-tag"><<span class="hljs-title">activity
</span>    <span class="hljs-attribute">android:name</span>=<span class="hljs-value">"com.kevintan.eventbussample.MainActivity"</span>
    <span class="hljs-attribute">android:theme</span>=<span class="hljs-value">"@style/AppTheme"</span>
    <span class="hljs-attribute">android:label</span>=<span class="hljs-value">"@string/app_name"</span> ></span>
    <span class="hljs-tag"><<span class="hljs-title">intent-filter</span>></span>
        <span class="hljs-tag"><<span class="hljs-title">action</span> <span class="hljs-attribute">android:name</span>=<span class="hljs-value">"android.intent.action.MAIN"</span> /></span>
        <span class="hljs-tag"><<span class="hljs-title">category</span> <span class="hljs-attribute">android:name</span>=<span class="hljs-value">"android.intent.category.LAUNCHER"</span> /></span>
    <span class="hljs-tag"></<span class="hljs-title">intent-filter</span>></span>
<span class="hljs-tag"></<span class="hljs-title">activity</span>></span></code><ul class="pre-numbering" style=""><li>1</li><li>2</li><li>3</li><li>4</li><li>5</li><li>6</li><li>7</li><li>8</li><li>9</li></ul><ul class="pre-numbering" style=""><li>1</li><li>2</li><li>3</li><li>4</li><li>5</li><li>6</li><li>7</li><li>8</li><li>9</li></ul>

最后,在style.xml中的AppTheme主题下增加MyCustomViewDefStyleAttr的引用实现.

<code class="language-xml hljs  has-numbering"><span class="hljs-tag"><<span class="hljs-title">style</span> <span class="hljs-attribute">name</span>=<span class="hljs-value">"AppTheme"</span> <span class="hljs-attribute">parent</span>=<span class="hljs-value">"android:Theme.Holo.Light.DarkActionBar"</span>></span><span class="css">
    <!<span class="hljs-tag">--</span> <span class="hljs-tag">Customize</span> <span class="hljs-tag">your</span> <span class="hljs-tag">theme</span> <span class="hljs-tag">here</span>. <span class="hljs-tag">--</span>>
    <<span class="hljs-tag">item</span> <span class="hljs-tag">name</span>="<span class="hljs-tag">MyCustomViewDefStyleAttr</span>"><span class="hljs-at_rule">@<span class="hljs-keyword">style/MyCustomViewDefStyleAttrImpl</item></span>
</span></span><span class="hljs-tag"></<span class="hljs-title">style</span>></span>

<span class="hljs-tag"><<span class="hljs-title">style</span> <span class="hljs-attribute">name</span>=<span class="hljs-value">"MyCustomViewDefStyleAttrImpl"</span>></span><span class="css">
    <<span class="hljs-tag">item</span> <span class="hljs-tag">name</span>="<span class="hljs-tag">custom_attr1</span>"><span class="hljs-tag">attr1_defStyleAttr</span></<span class="hljs-tag">item</span>>
    <<span class="hljs-tag">item</span> <span class="hljs-tag">name</span>="<span class="hljs-tag">custom_attr2</span>"><span class="hljs-tag">attr2_defStyleAttr</span></<span class="hljs-tag">item</span>>
    <<span class="hljs-tag">item</span> <span class="hljs-tag">name</span>="<span class="hljs-tag">custom_attr3</span>"><span class="hljs-tag">attr3_defStyleAttr</span></<span class="hljs-tag">item</span>>
</span><span class="hljs-tag"></<span class="hljs-title">style</span>></span></code><ul class="pre-numbering" style=""><li>1</li><li>2</li><li>3</li><li>4</li><li>5</li><li>6</li><li>7</li><li>8</li><li>9</li><li>10</li></ul><ul class="pre-numbering" style=""><li>1</li><li>2</li><li>3</li><li>4</li><li>5</li><li>6</li><li>7</li><li>8</li><li>9</li><li>10</li></ul>

代码验证,记住如果要使用obtainStyledAttributes方法的第三个参数, 就需要在第三个构造函数中显示的调用getTheme()的obtainStyledAttributes方法.

<code class="language-java hljs  has-numbering"><span class="hljs-keyword">public</span> <span class="hljs-title">MyCustomView</span>(Context context, AttributeSet attrs) {
    <span class="hljs-comment">// 为defStyleAttr进行赋值</span>
    <span class="hljs-keyword">this</span>(context, attrs, R.attr.MyCustomViewDefStyleAttr);
}

<span class="hljs-keyword">public</span> <span class="hljs-title">MyCustomView</span>(Context context, AttributeSet attrs, <span class="hljs-keyword">int</span> defStyleAttr) {
    <span class="hljs-keyword">super</span>(context, attrs, defStyleAttr);

    TypedArray ta = context.getTheme().obtainStyledAttributes(attrs, R.styleable.MyCustomView, defStyleAttr, <span class="hljs-number">0</span>);

    String attr1 = ta.getString(R.styleable.MyCustomView_custom_attr1);
    String attr2 = ta.getString(R.styleable.MyCustomView_custom_attr2);
    String attr3 = ta.getString(R.styleable.MyCustomView_custom_attr3);
    String attr4 = ta.getString(R.styleable.MyCustomView_custom_attr4);

    Log.e(<span class="hljs-string">"customview"</span>, <span class="hljs-string">"attr1="</span> + attr1);
    Log.e(<span class="hljs-string">"customview"</span>, <span class="hljs-string">"attr2="</span> + attr2);
    Log.e(<span class="hljs-string">"customview"</span>, <span class="hljs-string">"attr3="</span> + attr3);
    Log.e(<span class="hljs-string">"customview"</span>, <span class="hljs-string">"attr4="</span> + attr4);
    ta.recycle();
}</code><ul class="pre-numbering" style=""><li>1</li><li>2</li><li>3</li><li>4</li><li>5</li><li>6</li><li>7</li><li>8</li><li>9</li><li>10</li><li>11</li><li>12</li><li>13</li><li>14</li><li>15</li><li>16</li><li>17</li><li>18</li><li>19</li><li>20</li><li>21</li></ul><ul class="pre-numbering" style=""><li>1</li><li>2</li><li>3</li><li>4</li><li>5</li><li>6</li><li>7</li><li>8</li><li>9</li><li>10</li><li>11</li><li>12</li><li>13</li><li>14</li><li>15</li><li>16</li><li>17</li><li>18</li><li>19</li><li>20</li><li>21</li></ul>

代码中,有两点需要大家注意:

  1. 我在第二个构造参数中已经对defStyleAttr进行了赋值,第三个构造参数直接使用传入参数即可.
  2. 第三个构造参数中,我使用了getTheme()的obtainStyledAttributes方法来代替context的2个参数的obtainStyledAttributes构造方法.

示例结果:

<code class="language-text hljs mathematica has-numbering"><span class="hljs-number">05</span>-<span class="hljs-number">28</span> <span class="hljs-number">17</span>:<span class="hljs-number">19</span>:<span class="hljs-number">56.542</span> <span class="hljs-number">23575</span>-<span class="hljs-number">23575</span>/? <span class="hljs-keyword">E</span>/customview: attr1=attr1_xml
<span class="hljs-number">05</span>-<span class="hljs-number">28</span> <span class="hljs-number">17</span>:<span class="hljs-number">19</span>:<span class="hljs-number">56.542</span> <span class="hljs-number">23575</span>-<span class="hljs-number">23575</span>/? <span class="hljs-keyword">E</span>/customview: attr2=attr2_style
<span class="hljs-number">05</span>-<span class="hljs-number">28</span> <span class="hljs-number">17</span>:<span class="hljs-number">19</span>:<span class="hljs-number">56.542</span> <span class="hljs-number">23575</span>-<span class="hljs-number">23575</span>/? <span class="hljs-keyword">E</span>/customview: attr3=attr3_defStyleAttr
<span class="hljs-number">05</span>-<span class="hljs-number">28</span> <span class="hljs-number">17</span>:<span class="hljs-number">19</span>:<span class="hljs-number">56.542</span> <span class="hljs-number">23575</span>-<span class="hljs-number">23575</span>/? <span class="hljs-keyword">E</span>/customview: attr4=null</code><ul class="pre-numbering" style=""><li>1</li><li>2</li><li>3</li><li>4</li></ul><ul class="pre-numbering" style=""><li>1</li><li>2</li><li>3</li><li>4</li></ul>

从结果可以看出,在主题中指定style引用的优先级是低于在xml中直接赋值和使用style字段的.

同时,我们还需要了解一点:
在Android系统中的控件,很多都在构造参数中使用了第三个参数,例如Button.这样做的好处是: 当我们切换不同的主题时,Button的样式也能随之进行改变.


第四个参数——通过defStyleRes为属性赋值

这个参数的意思是:

  • 原文: A resource identifier of a style resource that supplies default values for the TypedArray, used only if defStyleAttr is 0 or can not be found in the theme. Can be 0 to not look for defaults.
  • 翻译: 这是一个指向Style的资源ID,但是仅在defStyleAttr为0或者defStyleAttr不为0但Theme中没有为defStyleAttr属性赋值时起作用.

通过翻译,我们可以明确两点:

  1. defStyleRes: 指向一个style引用.
  2. defStyleRes的优先级低于defStyleAttr.

为了验证,我们先在theme.xml文件中定义一个style:

<code class="language-xml hljs  has-numbering"><span class="hljs-tag"><<span class="hljs-title">style</span> <span class="hljs-attribute">name</span>=<span class="hljs-value">"MyCustomViewDefStyleRes"</span>></span><span class="css">
    <<span class="hljs-tag">item</span> <span class="hljs-tag">name</span>="<span class="hljs-tag">custom_attr1</span>"><span class="hljs-tag">attr1_defStyleRes</span></<span class="hljs-tag">item</span>>
    <<span class="hljs-tag">item</span> <span class="hljs-tag">name</span>="<span class="hljs-tag">custom_attr2</span>"><span class="hljs-tag">attr2_defStyleRes</span></<span class="hljs-tag">item</span>>
    <<span class="hljs-tag">item</span> <span class="hljs-tag">name</span>="<span class="hljs-tag">custom_attr3</span>"><span class="hljs-tag">attr3_defStyleRes</span></<span class="hljs-tag">item</span>>
    <<span class="hljs-tag">item</span> <span class="hljs-tag">name</span>="<span class="hljs-tag">custom_attr4</span>"><span class="hljs-tag">attr4_defStyleRes</span></<span class="hljs-tag">item</span>>
</span><span class="hljs-tag"></<span class="hljs-title">style</span>></span></code>

然后,我们在自定义View的第三个构造函数中的obtainStyledAttributes函数中进行赋值,具体方法如下:

<code class="language-java hljs  has-numbering"><span class="hljs-keyword">public</span> <span class="hljs-title">MyCustomView</span>(Context context, AttributeSet attrs) {
    <span class="hljs-keyword">this</span>(context, attrs, R.attr.MyCustomViewDefStyleAttr);
}

<span class="hljs-keyword">public</span> <span class="hljs-title">MyCustomView</span>(Context context, AttributeSet attrs, <span class="hljs-keyword">int</span> defStyleAttr) {
    <span class="hljs-keyword">super</span>(context, attrs, defStyleAttr);

    <span class="hljs-comment">// 为defStyleRes进行赋值</span>
    TypedArray ta = context.getTheme().obtainStyledAttributes(attrs, R.styleable.MyCustomView, defStyleAttr, R.style.MyCustomViewDefStyleRes);

    String attr1 = ta.getString(R.styleable.MyCustomView_custom_attr1);
    String attr2 = ta.getString(R.styleable.MyCustomView_custom_attr2);
    String attr3 = ta.getString(R.styleable.MyCustomView_custom_attr3);
    String attr4 = ta.getString(R.styleable.MyCustomView_custom_attr4);

    Log.e(<span class="hljs-string">"customview"</span>, <span class="hljs-string">"attr1="</span> + attr1);
    Log.e(<span class="hljs-string">"customview"</span>, <span class="hljs-string">"attr2="</span> + attr2);
    Log.e(<span class="hljs-string">"customview"</span>, <span class="hljs-string">"attr3="</span> + attr3);
    Log.e(<span class="hljs-string">"customview"</span>, <span class="hljs-string">"attr4="</span> + attr4);
    ta.recycle();
}</code><ul class="pre-numbering" style=""><li>1</li><li>2</li><li>3</li></ul>

测试结果:

<code class="language-text hljs mathematica has-numbering"><span class="hljs-number">05</span>-<span class="hljs-number">28</span> <span class="hljs-number">17</span>:<span class="hljs-number">44</span>:<span class="hljs-number">09.282</span> <span class="hljs-number">3137</span>-<span class="hljs-number">3137</span>/? <span class="hljs-keyword">E</span>/customview: attr1=attr1_xml
<span class="hljs-number">05</span>-<span class="hljs-number">28</span> <span class="hljs-number">17</span>:<span class="hljs-number">44</span>:<span class="hljs-number">09.282</span> <span class="hljs-number">3137</span>-<span class="hljs-number">3137</span>/? <span class="hljs-keyword">E</span>/customview: attr2=attr2_style
<span class="hljs-number">05</span>-<span class="hljs-number">28</span> <span class="hljs-number">17</span>:<span class="hljs-number">44</span>:<span class="hljs-number">09.282</span> <span class="hljs-number">3137</span>-<span class="hljs-number">3137</span>/? <span class="hljs-keyword">E</span>/customview: attr3=attr3_defStyleAttr
<span class="hljs-number">05</span>-<span class="hljs-number">28</span> <span class="hljs-number">17</span>:<span class="hljs-number">44</span>:<span class="hljs-number">09.282</span> <span class="hljs-number">3137</span>-<span class="hljs-number">3137</span>/? <span class="hljs-keyword">E</span>/customview: attr4=null</code><ul class="pre-numbering" style=""><li>4</li></ul>

重点:
如果大家认真的看实验结果,肯定会被上面的结果感到奇怪,明明指定了defStyleRes,为什么attr4的值还是null?
是因为之前讲过defStyleRes的使用优先级:只有当defStyleAttr为0或者当前Theme中没有给defStyleAttr属性赋值时才起作用.

所以,这里我们需要修改构造函数,将defStyleAttr设置为0.

<code class="language-java hljs  has-numbering"><span class="hljs-keyword">public</span> <span class="hljs-title">MyCustomView</span>(Context context, AttributeSet attrs) {
    <span class="hljs-comment">// 为了验证defStyleRes的作用,将defStyleAttr设置为0</span>
    <span class="hljs-keyword">this</span>(context, attrs, <span class="hljs-number">0</span>);
}

<span class="hljs-keyword">public</span> <span class="hljs-title">MyCustomView</span>(Context context, AttributeSet attrs, <span class="hljs-keyword">int</span> defStyleAttr) {
    <span class="hljs-keyword">super</span>(context, attrs, defStyleAttr);

    TypedArray ta = context.getTheme().obtainStyledAttributes(attrs, R.styleable.MyCustomView, defStyleAttr, R.style.MyCustomViewDefStyleRes);

    String attr1 = ta.getString(R.styleable.MyCustomView_custom_attr1);
    String attr2 = ta.getString(R.styleable.MyCustomView_custom_attr2);
    String attr3 = ta.getString(R.styleable.MyCustomView_custom_attr3);
    String attr4 = ta.getString(R.styleable.MyCustomView_custom_attr4);

    Log.e(<span class="hljs-string">"customview"</span>, <span class="hljs-string">"attr1="</span> + attr1);
    Log.e(<span class="hljs-string">"customview"</span>, <span class="hljs-string">"attr2="</span> + attr2);
    Log.e(<span class="hljs-string">"customview"</span>, <span class="hljs-string">"attr3="</span> + attr3);
    Log.e(<span class="hljs-string">"customview"</span>, <span class="hljs-string">"attr4="</span> + attr4);
    ta.recycle();
}</code>

最终结果:

<code class="language-text hljs mathematica has-numbering"><span class="hljs-number">05</span>-<span class="hljs-number">28</span> <span class="hljs-number">17</span>:<span class="hljs-number">49</span>:<span class="hljs-number">03.707</span> <span class="hljs-number">5772</span>-<span class="hljs-number">5772</span>/? <span class="hljs-keyword">E</span>/customview: attr1=attr1_xml
<span class="hljs-number">05</span>-<span class="hljs-number">28</span> <span class="hljs-number">17</span>:<span class="hljs-number">49</span>:<span class="hljs-number">03.707</span> <span class="hljs-number">5772</span>-<span class="hljs-number">5772</span>/? <span class="hljs-keyword">E</span>/customview: attr2=attr2_style
<span class="hljs-number">05</span>-<span class="hljs-number">28</span> <span class="hljs-number">17</span>:<span class="hljs-number">49</span>:<span class="hljs-number">03.707</span> <span class="hljs-number">5772</span>-<span class="hljs-number">5772</span>/? <span class="hljs-keyword">E</span>/customview: attr3=attr3_defStyleRes
<span class="hljs-number">05</span>-<span class="hljs-number">28</span> <span class="hljs-number">17</span>:<span class="hljs-number">49</span>:<span class="hljs-number">03.707</span> <span class="hljs-number">5772</span>-<span class="hljs-number">5772</span>/? <span class="hljs-keyword">E</span>/customview: attr4=attr4_defStyleRes</code>

后记

在文章结尾, 我们再次总结一下自定义属性的属性赋值优先级:

在布局xml中直接定义 > 在布局xml中通过style定义 > 自定义View所在的Activity的Theme中指定style引用 > 构造函数中defStyleRes指定的默认值

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
使用自定义View可以让你在Android应用中创建具有自定义外观和交互行为的组件。以下是使用自定义View的基本步骤: 1. 创建一个继承自View或其子类的Java类,作为自定义View的实现。 例如,你可以创建一个名为CustomView的类:`public class CustomView extends View` 2. 在自定义View构造函数中进行初始化和设置。 在构造函数中,你可以设置画笔、颜色、形状、属性等。你还可以处理触摸事件、测量和布局等。 例如,你可以在构造函数中初始化画笔:`Paint paint = new Paint();` 3. 重写onDraw()方法,在该方法中实现自定义View的绘制逻辑。 在onDraw()方法中,你可以使用Canvas对象绘制图形、文本等元素。通过调用invalidate()方法,可以触发View的重新绘制。 例如,你可以在onDraw()方法中使用画笔绘制一个圆:`canvas.drawCircle(x, y, radius, paint);` 4. 根据需要重写其他的方法,处理触摸事件、测量和布局等。 例如,你可以重写onTouchEvent()方法来处理触摸事件,并根据手势改变自定义View的状态。 5. 在XML布局文件或代码中使用自定义View。 如果你希望在XML布局文件中使用自定义View,可以在XML文件中添加相应的标签,并指定自定义View的包名和类名。 例如,你可以在XML布局中添加一个CustomView:`<com.example.app.CustomView android:layout_width="match_parent" android:layout_height="match_parent"/>` 以上是使用自定义View的基本步骤。当你使用自定义View,可以根据自己的需求定制其外观和行为,并根据需要处理相关事件。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值