最近在學習的過程中遇到了自定義的attr和自定義的style。因此各種百度,各種博客的學習,算是有了一個系統的了解。在這里記錄下自己的收獲。
一、為什么要使用自定義attr以及本文定位
在android開發中,很多時候需要我們自定義view,這其中就包含了一個view的很多屬性的設置。有時候會出現android本身提供的屬性並不夠用(比如它針對某些控件提供的text屬性,color屬性等),又或者我們想將android系統提供的屬性集成到一起形成自己的一套屬性集合。那么這個時候,就需要我們來自定義一套自己的屬性,這就是自定義attr。因此自定義attr與自定義view是密切關聯的。對於自定義attr更加深入的理解,在這里推薦我十分佩服的一位大神的博客文章http://blog.csdn.net/lmj623565791/article/details/45022631
但是建議你還是閱讀完本文,再去點擊上面的鏈接。因為本文將手把手帶你去實現一個自定義的attr,這樣子你會了解整個自定義attr流程。既然是手把手,所以本文不會涉及到原理性的東西,而且代碼十分簡單易懂,因為我也是初學者,所以力求將一個初學者學習的過程展現出來,當然其中的某些疑問可能對於anroid老鳥來說是十分幼稚的。不過知識就是這樣子一點點一步步收獲起來的。好了,廢話不多說,進入正文吧。
二、你必須要了解的
首先實現一個自定義attr的流程:
(1)先有一個自定義的view(它是你所自定義attr的使用者)
(2)然后在values文件夾下建立attrs.xml文件,編寫你的自定義的屬性。示例代碼如下:
1 <?xml version="1.0" encoding="utf-8"?> 2 <resources> 3 4 <declare-styleable name="test"> 5 <attr name="text" format="string" /> 6 <attr name="testAttr" format="integer" /> 7 </declare-styleable> 8 9 </resources>
(3)在xml文件中使用自定義屬性,為它賦值
(4)在自定義view中使用TypedArray獲取你所賦的值,並用作其他用途。
現在主要說明編寫自定義屬性的代碼中,即上面的xml文件中,format的含義。其實format就是為自定義的屬性設置一個格式。這根android給我們提供的屬性是一樣的道理,比如android給我們提供的text的屬性格式就是string類型的,在我們為一個TextView設置text的時候可不就是寫一個字符串嘛。那么上面的代碼的意思就是自定義的屬性text,格式是string類型,testAttr,類型是integer。下面來看一個format都可以指定為什么。如下:
format還可以指定其他的類型比如; reference 表示引用,參考某一資源ID string 表示字符串 color 表示顏色值 dimension 表示尺寸值 boolean 表示布爾值 integer 表示整型值 float 表示浮點值 fraction 表示百分數 enum 表示枚舉值 flag 表示位運算
可能還還有其他的疑問,比如其他關鍵字的含義是什么,以及是怎么使用自定義attr的。甚至還有很細的說不清的疑問。如果沒有實際代碼的話,很難說明白這些疑問。所以跟着我來往下一步一步寫一個例子出來吧,在這個過程中,相信你的疑問應該會被解開。
三、實現自定義attr,同時解答細節上的疑問
在這個例子中,我們來實現超級簡單的自定義view,在屏幕上寫用畫筆寫出一個字符串出來。純粹是為了說明自定義attr的實現過程的。而字符串的顏色以及字符串的內容,就采用自定義屬性的方式來獲取。我們心中已經有了這個自定義的view的大概了,下面就開始編寫自定義attr吧。
新建項目,然后在它的res/values下面新建attrs.xml文件,代碼如下:
1 <?xml version="1.0" encoding="utf-8"?> 2 <resources> 3 <declare-styleable name="MyView"> 4 <attr name="myText" format="string"/> 5 <attr name="myColor" format="color"/> 6 </declare-styleable> 7 </resources>
從代碼中我們可以看到,自定義了兩個屬性,myText和myColor,類型分別為string何color。然后要說明兩點:
(1)你可以將declare-styleable看成一個集合的名稱,而它里面的元素就是我們自定義的屬性。它可以命名為任意名稱,不過一般都命名為相應的自定義的view的名稱,表示是為這個view定制的屬性,也方便查閱。在這里我隨便命名了一個名字,為MyView。通過這個名稱就可以找到我們自定義的屬性。resources標簽下可以有多個declare-styleable的。
(2)標簽attr下的name就是自定義的屬性名,可以任意命名,format為其格式類型。
你肯定還在疑問,自定義的屬性都自定義好了,怎么用呢?那么我們現在就來使用它。首先將與之相關的自定義的view先建出來。新建類CustomView繼承自view,代碼如下:
1 package com.fuly.kun; 2 3 import android.content.Context; 4 5 import android.view.View; 6 7 public class CustomView extends View { 8 9 public CustomView(Context context, AttributeSet attrs) { 10 super(context, attrs); 11 12 } 13 14 }
代碼很簡單,在這個自定義的view中,我們什么都沒有做。這個view肯定是要顯示出來的,那么我就修改activity_main.xml的代碼,將其顯示出來。注意這個時候,就該為CustomView設定屬性了,此時就開始使用自定義的attr了。好了,快看代碼吧,代碼:
1 <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" 2 xmlns:tools="http://schemas.android.com/tools" 3 xmlns:fuly="http://schemas.android.com/apk/res/com.fuly.kun" 4 android:layout_width="match_parent" 5 android:layout_height="match_parent" 6 > 7 8 <com.fuly.kun.CustomView 9 android:layout_width="wrap_content" 10 android:layout_height="wrap_content" 11 fuly:myText="我是自定義attr" 12 fuly:myColor="#00ff00"/> 13 </RelativeLayout>
代碼很簡單,我們給自定義的view賦了屬性值。是不是發現了什么,有些代碼跟你之前用的不一樣!下面我們就來詳細說明一下怎么就把自定義的屬性給使用進來了。如下說明:
(1)首先觀察代碼的第3行,這句話就是引入了我們項目中自定義的attr。是不是發現第三行和第一行的代碼很像,其實你現在明白了吧,第一行其實就是因為android系統給出的屬性,所以下面我們才能使用android:layout_width等。因為引入自定義attr,主要將后綴的android替換成為項目的包名即可,即替換為了Manifest.xml下的package標簽下的包名。而我們將引入的自定義attr命名為了fuly,然后在使用自定義屬性時就借助fuly來找到我們自定義的屬性名稱了。fuly這個名稱可以隨便指定,沒有什么規則。
(2)再觀察第11行和第12行的代碼,跟第9行和第10行的代碼是不是很像,這就是在CustomView使用自定義的屬性,並為其賦值(一定要注意和其格式類型要相同)。
好了,現在要修改CustomView的代碼了。獲取到我們自定義的屬性值,並使用它。這其實跟android獲取自帶的屬性是一樣的道理,比如我們給一個TextView的text賦了一個字符串,然后在代碼中使用getText()方法就可以這個字符串,即給text所賦的屬性值。好了,快看代碼吧,如下:
1 package com.fuly.kun; 2 3 import android.content.Context; 4 import android.content.res.TypedArray; 5 import android.graphics.Canvas; 6 import android.graphics.Paint; 7 import android.util.AttributeSet; 8 import android.view.View; 9 10 public class CustomView extends View { 11 12 private TypedArray ta;//用來獲取自定義屬性的 13 14 15 public CustomView(Context context, AttributeSet attrs) { 16 super(context, attrs); 17 //獲取到我們自定義的屬性 18 ta = context.obtainStyledAttributes(attrs, R.styleable.MyView); 19 } 20 21 protected void onDraw(Canvas canvas) { 22 23 super.onDraw(canvas); 24 //獲取到我們為自定義的屬性所賦的值 25 String text = ta.getString(R.styleable.MyView_myText); 26 int color = ta.getColor(R.styleable.MyView_myColor, 003300); 27 28 Paint paint = new Paint(); 29 paint.setColor(color); 30 paint.setTextSize(55); 31 canvas.drawText(text, 100, 100, paint); 32 } 33 34 }
代碼很簡單。只不過就牽涉了一個知識點,獲取自定義屬性的值,要使用TypedArray這個類而已。在代碼的第18行,我們獲取了一個TypedArray實例,而且這個實例是跟我們自定義的屬性集合MyView相關聯的。然后再代碼的第25和26行,就可以用這個TypedArray對象獲取自定義屬性的值了。注意ta.getColor的第二個參數意思是如果該屬性沒有賦值,就返回顏色“#003300”。然后我們將獲取到的文本和顏色作用到畫筆和畫布上即可。
好了,MainActivtity中的代碼已經加載了acitivty_main.xml布局,不需要更改。下面我們直接運行效果,如下:
小結:
主要是TypedArray的對象的獲得,是通過Context的,如下:
ta = context.obtainStyledAttributes(attrs, R.styleable.MyView);
關於它的一系列方法,可以翻看API文檔,這里總結沒有什么意義。
好了,相信對自定義attr有了一個初步的了解了吧。以后程序開發中要比這個里復雜的多。學習進階,不要怕難,貴在堅持!一起進步
