<output id="qn6qe"></output>

    1. <output id="qn6qe"><tt id="qn6qe"></tt></output>
    2. <strike id="qn6qe"></strike>

      亚洲 日本 欧洲 欧美 视频,日韩中文字幕有码av,一本一道av中文字幕无码,国产线播放免费人成视频播放,人妻少妇偷人无码视频,日夜啪啪一区二区三区,国产尤物精品自在拍视频首页,久热这里只有精品12

      Android中自定義樣式與View的構(gòu)造函數(shù)中的第三個(gè)參數(shù)defStyle的意義

      零、序

      一、自定義Style

      二、在XML中為屬性聲明屬性值

        1. 在layout中定義屬性

        2. 設(shè)置Style

        3. 通過Theme指定

      三、在運(yùn)行時(shí)獲取屬性值

        1. View的第三個(gè)構(gòu)造函數(shù)的第三個(gè)參數(shù)defStyle

        2. obtailStyledAttributes

        3. Example

      四、結(jié)論與代碼下載

      零、序

        系統(tǒng)自帶的View可以在xml中配置屬性,對(duì)于寫的好的Custom View同樣可以在xml中配置屬性,為了使自定義的View的屬性可以在xml中配置,需要以下4個(gè)步驟:

        1. 通過<declare-styleable>為自定義View添加屬性

        2. 在xml中為相應(yīng)的屬性聲明屬性值

        3. 在運(yùn)行時(shí)(一般為構(gòu)造函數(shù))獲取屬性值

        4. 將獲取到的屬性值應(yīng)用到View

        怎么將獲取到的屬性值應(yīng)用到View就不用說了,自己定義的屬性什么用處自己肯定是清楚的,所以接下來看一下前三點(diǎn)。

      一、自定義Style

        通過<declare-styleable>元素聲明Custom View需要的屬性即可,下面是一個(gè)例子,文件是res/values/attrs.xml

      <?xml version="1.0" encoding="utf-8"?>
      <resources>
          <declare-styleable name="Customize">
              <attr name="attr_one" format="string" />
              <attr name="attr_two" format="string" />
              <attr name="attr_three" format="string" />
              <attr name="attr_four" format="string" />
          </declare-styleable>
       
          <attr name="CustomizeStyle" format="reference" />
      </resources>

        在上述xml中,我們聲明了Customize與CustomizeSyle,Customize包含了attr_one、attr_two、attr_three與attr_four四個(gè)attribute,CustomizeStyle也是一個(gè)attribute,但是卻沒有聲明在declare-styleable中。

        定義在declare-styleable中與直接用attr定義沒有實(shí)質(zhì)的不同,上述xml中,無論attr_one - attr_four是否聲明在declare-styleable中,系統(tǒng)都會(huì)為我們?cè)赗.attr中生成5個(gè)attribute

      public static final class attr {
          public static final int CustomizeStyle=0x7f010004;
          public static final int attr_one=0x7f010000;
          public static final int attr_two=0x7f010001;
          public static final int attr_three=0x7f010002;
          public static final int attr_four=0x7f010003;
      }

        不同的是,如果聲明在declare-styleable中,系統(tǒng)還會(huì)為我們?cè)赗.styleable中生成相關(guān)的屬性。

      public static final class styleable {
          public static final int[] Customize = {
              0x7f010000, 0x7f010001, 0x7f010002, 0x7f010003
          };
          public static final int Customize_attr_one = 0;
          public static final int Customize_attr_two = 1;    
          public static final int Customize_attr_three = 2;
          public static final int Customize_attr_four = 3;
      }

         如上所示,R.styleable.Customize是一個(gè)int[],而里面的元素的值正好和R.attr.attr_one - R.attr.attr_four一一對(duì)應(yīng),而R.styleable.Customize_attr_one等4個(gè)值就是R.attr.attr_one-R.attr.attr_four在R.styleable.Customize數(shù)組中的索引。這個(gè)數(shù)組和索引在第三步運(yùn)行時(shí)獲得屬性值時(shí)會(huì)用到,將attr分組聲明在declare-styleabe中的作用就是系統(tǒng)會(huì)自動(dòng)為我們生成這些東西,如果不聲明在declare-styleable中,我們完全可以在需要的時(shí)候自己構(gòu)建這個(gè)數(shù)組,由于數(shù)組是自己構(gòu)建的,每個(gè)屬性的下標(biāo)索引也就很清楚了,只是比較麻煩。以上一家之言,不過從使用及實(shí)驗(yàn)難上看確實(shí)是這樣的。

      二、在xml中為相應(yīng)的屬性聲明屬性值

              我們知道,在xml中為屬性賦值有幾種不同的方式

      1. 直接在layout中使用屬性

      2. 設(shè)置style并在style中設(shè)置屬性

      3. Application和Activity可以指定theme,可以在theme中指定在當(dāng)前Application或Activity中屬性的默認(rèn)值

              下面就分別看一下這三種方式

      1. 直接在layout中使用屬性

              在xml layout中使用自定義屬性和使用系統(tǒng)屬性差不多,不過屬性所屬的namespace不同,比如像下面這樣。

      <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
          xmlns:ad="http://schemas.android.com/apk/res/com.angeldevil.customstyle"
          xmlns:tools="http://schemas.android.com/tools"
          android:layout_width="match_parent"
          android:layout_height="match_parent"
          tools:context=".MainActivity" >
      
          <com.angeldevil.customstyle.CustomTextView
              android:layout_width="wrap_content"
              android:layout_height="wrap_content"
              ad:attr_one="attr one in xml"
              style="@style/ThroughStyle"
              android:text="@string/hello_world" />
      
      </RelativeLayout>

        像layout_width等屬性屬于android的namespace,自定義的屬性屬于當(dāng)前程序的namespace,只需像聲明android的namespace一樣聲明當(dāng)前程序的namespace就好,只需要把上面紅色部分的android換成當(dāng)前程序的包名。應(yīng)用屬性的時(shí)候也需要注意屬性的namespace。

      2. 設(shè)置style并在style中設(shè)置屬性

        看上面xml中綠色的那一行,我們?yōu)镃ustomTextView聲明了一個(gè)style:ThroughStyle,這個(gè)Style很簡(jiǎn)單,只是指定了兩個(gè)屬性的值

      <style name="ThroughStyle">
          <item name="attr_one">attr one from style</item>
          <item name="attr_two">attr two from style</item>
      </style>

        注意,在style中我們聲明了attr_one的值,同時(shí)在xml中也直接向attr_one賦了值,最終用哪一個(gè)有個(gè)優(yōu)先級(jí)的問題,后面在第三節(jié):在運(yùn)行時(shí)獲取屬性值中再說,接下來看下第三種方式。

      3. theme中指定在當(dāng)前Application或Activity中屬性的默認(rèn)值

      <!-- Application theme. -->
      <style name="AppTheme" parent="AppBaseTheme">
          <!-- All customizations that are NOT specific to a particular API-level can go here. -->
          <item name="attr_one">attr one from theme</item>
          <item name="attr_two">attr two from theme</item>
          <item name="attr_three">attr three from theme</item>
          <item name="CustomizeStyle">@style/CustomizeStyleInTheme</item>
      </style>
      
      <style name="CustomizeStyleInTheme">
          <item name="attr_one">attr one from theme reference</item>
          <item name="attr_two">attr two from theme reference</item>
          <item name="attr_three">attr three from theme reference</item>
      </style>

         在上述xml中,我們?cè)贏ppTheme中為attr_one、attr_two與attr_three指定了值,但是同時(shí)也為CustomizeStyle指定了一個(gè)reference,而在這個(gè)reference中為attr_one、attr_two與attr_three指定了值,CustomizeStyle就是我們?cè)赼ttrs.xml中定義的一個(gè)屬性。在theme中為屬性設(shè)置值的方式有兩這種,直接在theme中定義或通過另一個(gè)attribute引用一個(gè)style,這兩種方式還是有區(qū)別的,在下面的獲取屬性值一節(jié)中可以看到。

      三、在運(yùn)行時(shí)獲取屬性值

              在styles.xml中,我們同時(shí)定義一個(gè)DefaultCustomizeStyle的style,它的作用等下可以看到。

      <style name="DefaultCustomizeStyle">
          <item name="attr_one">attr one from defalut style res</item>
          <item name="attr_two">attr two from defalut style res</item>
          <item name="attr_three">attr three from defalut style res</item>
      </style>

        先看下CustomTextView的代碼

      public class CustomTextView extends TextView {
          private static final String TAG = CustomTextView.class.getSimpleName();
      
          public CustomTextView(Context context) {
              super(context);
          }
      
          public CustomTextView(Context context, AttributeSet attrs) {
              this(context, attrs, R.attr.CustomizeStyle);
          }
      
          public CustomTextView(Context context, AttributeSet attrs, int defStyle) {
              super(context, attrs, defStyle);
              TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.Customize, defStyle, R.style.DefaultCustomizeStyle);
              String one = a.getString(R.styleable.Customize_attr_one);
              String two = a.getString(R.styleable.Customize_attr_two);
              String three = a.getString(R.styleable.Customize_attr_three);
              String four = a.getString(R.styleable.Customize_attr_four);
              Log.i(TAG, "one:" + one);
              Log.i(TAG, "two:" + two);
              Log.i(TAG, "three:" + three);
              Log.i(TAG, "four:" + four);
              a.recycle();
          }
      }

         主要代碼都在第三個(gè)函數(shù)中,這里也沒做什么,只是通過Context的obtainStyledAttributes獲得了前面定義的4個(gè)屬性的值并打印了出來。

      View的第三個(gè)構(gòu)造函數(shù)的第三個(gè)參數(shù)defStyle

        如果在Code中實(shí)例化一個(gè)View會(huì)調(diào)用第一個(gè)構(gòu)造函數(shù),如果在xml中定義會(huì)調(diào)用第二個(gè)構(gòu)造函數(shù),而第三個(gè)函數(shù)系統(tǒng)是不調(diào)用的,要由View(我們自定義的或系統(tǒng)預(yù)定義的View,如此處的CustomTextView和Button)顯式調(diào)用,比如在這里我們?cè)诘诙€(gè)構(gòu)造函數(shù)中調(diào)用了第三個(gè)構(gòu)造函數(shù),并將R.attr.CustomizeStyle傳給了第三個(gè)參數(shù)。

        第三個(gè)參數(shù)的意義就如同它的名字所說的,是默認(rèn)的Style,只是這里沒有說清楚,這里的默認(rèn)的Style是指它在當(dāng)前Application或Activity所用的Theme中的默認(rèn)Style,以系統(tǒng)中的Button為例說明。

      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 defStyle) {
          super(context, attrs, defStyle);
      }

         在Code中實(shí)例化View會(huì)調(diào)用第一個(gè)構(gòu)造函數(shù),在XML中定義會(huì)調(diào)用第二個(gè)構(gòu)造函數(shù),在Button的實(shí)現(xiàn)中都調(diào)用了第三個(gè)構(gòu)造函數(shù),并且defStyle的值是com.android.internal.R.attr.buttonStyle。buttonStyle是系統(tǒng)中定義的一個(gè)attribute,系統(tǒng)默認(rèn)有一個(gè)Theme,比如4.0中是Theme.Holo

      <style name="Theme.DeviceDefault" parent="Theme.Holo" >
          ...
          <item name="buttonStyle">@android:style/Widget.DeviceDefault.Button</item>
          ....
      </style>

        上面是系統(tǒng)默認(rèn)的Theme,為buttonStyle指定了一個(gè)Style

      <style name="Widget.DeviceDefault.Button" parent="Widget.Holo.Button" >
      </style>
      
      <style name="Widget.Holo.Button" parent="Widget.Button">
      <item name="android:background">@android:drawable/btn_default_holo_dark</item>
          <item name="android:textAppearance">?android:attr/textAppearanceMedium</item>
          <item name="android:textColor">@android:color/primary_text_holo_dark</item>
          <item name="android:minHeight">48dip</item>
          <item name="android:minWidth">64dip</item>
      </style>

         這個(gè)Style定義了系統(tǒng)中Button的默認(rèn)屬性,如background等。

        從文檔中第三個(gè)構(gòu)造函數(shù)的說明中也可以看到,這個(gè)構(gòu)造函數(shù)的作用是View的子類提供這個(gè)類的基礎(chǔ)樣式

      View(Context context, AttributeSet attrs, int defStyleAttr)

      Perform inflation from XML and apply a class-specific base style.

        上面說的都比較抽象,還是直接看實(shí)例代碼來的清楚明白,實(shí)驗(yàn)用的代碼上面全都貼完了,這里直接看結(jié)果,但在這之前要先看一個(gè)函數(shù):obtainStyledAtributes。

      obtainStyledAtributes

        我們要獲取的屬性值都是通過這個(gè)函數(shù)返回的TypedArray獲得的,這是官方說明:obtainStyledAttributes,以下是函數(shù)原型:

      public TypedArray obtainStyledAttributes (AttributeSet set, int[] attrs, int defStyleAttr, int defStyleRes)

        4個(gè)參數(shù)的意思分別是:

          set:屬性值的集合

          attrs:我們要獲取的屬性的資源ID的一個(gè)數(shù)組,如同ContextProvider中請(qǐng)求數(shù)據(jù)庫(kù)時(shí)的Projection數(shù)組,就是從一堆屬性中我們希望查詢什么屬性的值

          defStyleAttr:這個(gè)是當(dāng)前Theme中的一個(gè)attribute,是指向style的一個(gè)引用,當(dāng)在layout xml中和style中都沒有為View指定屬性時(shí),會(huì)從Theme中這個(gè)attribute指向的Style中查找相應(yīng)的屬性值,這就是defStyle的意思,如果沒有指定屬性值,就用這個(gè)值,所以是默認(rèn)值,但這個(gè)attribute要在Theme中指定,且是指向一個(gè)Style的引用,如果這個(gè)參數(shù)傳入0表示不向Theme中搜索默認(rèn)值

          defStyleRes:這個(gè)也是指向一個(gè)Style的資源ID,但是僅在defStyleAttr為0或defStyleAttr不為0但Theme中沒有為defStyleAttr屬性賦值時(shí)起作用

        鏈接中對(duì)這個(gè)函數(shù)說明勉強(qiáng)過得去,這里簡(jiǎn)要概括一下。對(duì)于一個(gè)屬性可以在多個(gè)地方指定它的值,如XML直接定義,style,Theme,而這些位置定義的值有一個(gè)優(yōu)先級(jí),按優(yōu)先級(jí)從高到低依次是:

      直接在XML中定義>style定義>由defStyleAttr和defStyleRes指定的默認(rèn)值>直接在Theme中指定的值

        看這個(gè)關(guān)系式就比較明白了,defStyleAttr和defStyleRes在前面的參數(shù)說明中已經(jīng)說了,“直接在Theme中指定的值”的意思在下面的示代碼中可以看到。

      實(shí)驗(yàn)驗(yàn)證

        相關(guān)的代碼都前面都已經(jīng)貼上了,不過為了方便查看,這里再把相關(guān)的XML一起貼一遍

      main_activity.xml
      <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
          xmlns:ad="http://schemas.android.com/apk/res/com.angeldevil.customstyle"
          xmlns:tools="http://schemas.android.com/tools"
          android:layout_width="match_parent"
          android:layout_height="match_parent"
          tools:context=".MainActivity" >
      
          <com.angeldevil.customstyle.CustomTextView
              android:layout_width="wrap_content"
              android:layout_height="wrap_content"
              ad:attr_one="attr one in xml"
              style="@style/ThroughStyle"
              android:text="@string/hello_world" />
      
      </RelativeLayout>
      
      attrs.xml
      <?xml version="1.0" encoding="utf-8"?>
      <resources>
      
          <declare-styleable name="Customize">
              <attr name="attr_one" format="string" />
              <attr name="attr_two" format="string" />
              <attr name="attr_three" format="string" />
              <attr name="attr_four" format="string" />
          </declare-styleable>
      
          <attr name="CustomizeStyle" format="reference" />
      
      </resources>
      
      styles.xml
      <resources>
      
          <style name="AppBaseTheme" parent="android:Theme.Light">
          </style>
          <!-- Application theme. -->
          <style name="AppTheme" parent="AppBaseTheme">
              <!-- All customizations that are NOT specific to a particular API-level can go here. -->
              <item name="attr_one">attr one from theme</item>
              <item name="attr_two">attr two from theme</item>
              <item name="attr_three">attr three from theme</item>
              <item name="CustomizeStyle">@style/CustomizeStyleInTheme</item>
          </style>
      
          <style name="CustomizeStyleInTheme">
              <item name="attr_one">attr one from theme reference</item>
              <item name="attr_two">attr two from theme reference</item>
              <item name="attr_three">attr three from theme reference</item>
          </style>
      
          <style name="ThroughStyle">
              <item name="attr_one">attr one from style</item>
              <item name="attr_two">attr two from style</item>
          </style>
          
          <style name="DefaultCustomizeStyle">
              <item name="attr_one">attr one from defalut style res</item>
              <item name="attr_two">attr two from defalut style res</item>
              <item name="attr_three">attr three from defalut style res</item>
          </style>
      
      </resources>

         在Code中是這樣獲取屬性的

      public CustomTextView(Context context, AttributeSet attrs) {
          this(context, attrs, R.attr.CustomizeStyle);
      }
      
      public CustomTextView(Context context, AttributeSet attrs, int defStyle) {
          super(context, attrs, defStyle);
              
          TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.Customize, defStyle,
                      R.style.DefaultCustomizeStyle);
          ...
      }

        CustomizeStyle是定義的一個(gè)attribute,DefaultCustomizeStyle是定義的一個(gè)style。

        從代碼中可以看到,R.attr.CustomizeStyle就是前面提到的defStyleAttr,R.style.DefaultCustomizeStyle就是defStyleRes。

        在Styles.xml中我們?yōu)锳pp定義了一個(gè)Theme:AppTheme,在這個(gè)Theme中直接為attr_one、attr_two、attr_three定義了屬性值,這個(gè)就是前面關(guān)系式中說的直接在Theme中指定的值。

        在AppTheme中同時(shí)定義了CustomizeStyle,引用了一個(gè)Style,在CustomTextView的構(gòu)造函數(shù)中分別打印了attr_one、attr_two、attr_three、attr_four的值,所以下面我們就可以通過Log輸出驗(yàn)證一下前面的關(guān)系式,如果一個(gè)attribute在多個(gè)位置都定義了值,究竟哪一個(gè)起作用。

        

        如上圖所示:

        • attr_one同時(shí)在xml、style、defStyleAttr、defStyleRes與Theme中直接定義了值,但起作用的是在xml中的定義
        • attr_two同時(shí)在style、defStyleAttr、defStyleRes與Theme中直接定義了值,但起用的是在style中的定義
        • attr_three同時(shí)在defStyleAttr、defStyleRes與Theme中直接定義了值,但起作用的是defStyleAttr
        • attr_four在defStyleRes中定義了,但結(jié)果仍是0。

        這可以說明:

      1. 直接在XML中定義>style定義>由defStyleAttr定義的值>defStyleRes指定的默認(rèn)值、直接在Theme中指定的值

      2. defStyleAttr(即defStyle)不為0且在當(dāng)前Theme中可以找到這個(gè)attribute的定義時(shí),defStyleRes不起作用,所以attr_four雖然在defStyleRes(DefaultCustomizeStyle)中定義了,但取到的值仍為null。

        為了看一下defStyleRes的作用,1. 我們?cè)贏ppTheme中加上attr_four的定義,2. 向obtainStyledAttributes的第三個(gè)參數(shù)傳入0,或者移除AppTheme中CustomizeStyle的定義,結(jié)果是一樣的

      <style name="AppTheme" parent="AppBaseTheme">
          <item name="attr_one">attr one from theme</item>
          <item name="attr_two">attr two from theme</item>
          <item name="attr_three">attr three from theme</item>
          <item name="attr_four">attr four from theme</item>
      </style>

         由于defStyleAttr為0,或者defStyleAttr不為0但是我們沒有為這個(gè)屬性賦值,所以defStyleRes起作用,當(dāng)一個(gè)屬性沒有在XML和Style中賦值時(shí),系統(tǒng)會(huì)在defStyleRes(此處為DefaultCustomizeStyle)查找屬性的值。

        

        我們看到attr_three的值來自defStyleRes,而attr_four的值來自Theme中的直接定義(DefaultCustomizeStyle定義了attr_one、atrr_two、attr_three) ,這就說明

      1. defStyleAtrtr即defStyle為0或Theme中沒有定義defStyle時(shí)defStyleRes才起作用

      2. defStyleRes>在Theme中直接定義

       結(jié)論

         從前面的說明可以得到以下結(jié)論:

        1. 要為自定義View自定義屬性,可以通過declare-styleable聲明需要的屬性
        2. 為了在Theme設(shè)置View的默認(rèn)樣式,可以同時(shí)定義一個(gè)format為reference的屬性att_a,在定義Theme時(shí)為這個(gè)attribute指定一個(gè)Style,并且在View的第二個(gè)構(gòu)造函數(shù)中將R.attr.attr_a 作為第三個(gè)參數(shù)調(diào)用第三個(gè)構(gòu)造函數(shù)
        3. 可以定義一個(gè)Style作為Theme中沒有定義attr_a時(shí)View屬性的默認(rèn)值。
        4. 可以在Theme中直接為屬性賦值,但優(yōu)先級(jí)最低
        5. 當(dāng)defStyleAttr(即View的構(gòu)造函數(shù)的第三個(gè)參數(shù))不為0且在Theme中有為這個(gè)attr賦值時(shí),defStyleRes(通過obtainStyledAttributes的第四個(gè)參數(shù)指定)不起作用
        6. 屬性值定義的優(yōu)先級(jí):xml>style>Theme中的默認(rèn)Sytle>默認(rèn)Style(通過obtainStyledAttributes的第四個(gè)參數(shù)指定)>在Theme中直接指定屬性值

        代碼下載:CustomStyle.zip

      posted @ 2013-12-18 13:32  AngelDevil  閱讀(44067)  評(píng)論(16)    收藏  舉報(bào)
      主站蜘蛛池模板: 少妇人妻互换不带套| 国产精品剧情亚洲二区| 天堂在/线中文在线资源 官网| 久久久久免费看成人影片| 久久精品色一情一乱一伦| AV最新高清无码专区| 成人午夜免费无码视频在线观看| 亚洲爆乳成av人在线视菜奈实| 在线中文字幕亚洲日韩2020| 扒开女人内裤猛进猛出免费视频| 人人妻碰人人免费| 国产偷窥熟女高潮精品视频| 国产va免费精品观看| 亚洲线精品一区二区三八戒| 精品人妻av中文字幕乱| 亚洲春色在线视频| 天堂va蜜桃一区二区三区| 亚州av第二区国产精品| 艳妇臀荡乳欲伦交换在线播放| 中文字幕国产精品第一页| 人妻av无码系列一区二区三区| 国产精品成人一区二区不卡 | 色悠悠成人综合在线视频| 综合偷自拍亚洲乱中文字幕| 国产偷自视频区视频| 九九热在线精品视频九九| 久久精品网站免费观看| 天堂资源国产老熟女在线| 国产欧美综合在线观看第十页| 民县| 国产国产久热这里只有精品| 免费无码成人AV片在线 | 最新亚洲精品国偷自产在线| 亚洲一区二区偷拍精品| 久久综合色一综合色88| 亚洲国产在一区二区三区| 少妇办公室好紧好爽再浪一点| 国产成人久久蜜一区二区| 大香伊蕉在人线国产免费| 国产一区二区日韩在线| 好吊视频在线一区二区三区|