<a href="http://www.cnblogs.com/sunshine-anycall/p/5448108.html">Android自定義視圖一:擴充現有的視圖,添加新的XML屬性</a>
<a href="http://www.cnblogs.com/sunshine-anycall/p/5460023.html">Android自定義視圖二:如何繪制内容</a>
<a href="http://www.cnblogs.com/sunshine-anycall/p/5466067.html">Android自定義視圖三:給自定義視圖添加“流暢”的動畫</a>
<a href="http://www.cnblogs.com/sunshine-anycall/p/5470984.html">Android自定義視圖四:定制onMeasure強制顯示為方形</a>
這個系列詳細的介紹了如何穿件Android自定義視圖。主要涉及的内容有如何繪制内容,layout和measure的原理,如何繼承實作view group以及如何給其子視圖添加動畫。第一篇主要講述如何擴充和使用現有的視圖,以及如何添加特有的XML屬性。
Android提供的view都是比較通用的,哪裡都可以用。但是在開發應用的過程中需要對這些通用的view加以修改。很多時候這些代碼都添加到了Activity中,這樣是的Activity的代碼雜亂,影響維護。
假設你在開發一個最用使用者訓練資料的應用。比如使用者的總運動時長,總運動距離以及不同的運動類型等。為了友好的把資料展現給使用者,你需要根據使用者運動的時間長度做不同的處理。比如他運動了2378秒,那麼顯示的肯定是48分鐘。18550秒,那顯示的肯定是5小時9分鐘。
處理上面的問題最好就是定義一個view。這個view裡包含了處理上面時間的功能。我們來建立一個自定義view:<code>DurationTextView</code>。
<code>TextView</code>和其他的view一樣有三個構造函數:一個是隻需要<code>Context</code>的,一個是上面給出的需要兩個參數<code>Context</code>和<code>AttributeSet</code>,還有一個需要這兩個參數之外的關于style的參數。一般來說,上面給出的構造方法就可以滿足。下面在布局中使用上面定義的view。
注意,這裡需要給出自定義視圖的全名稱。
現在這個視圖和标準的<code>TextView</code>沒什麼太大的差別。我們為這個view添加一個<code>duration</code>屬性來設定和讀取duration值。
這個方法接受一個<code>Float</code>型的參數,訓練時間的秒數。然後通過上面的轉換邏輯把這個秒數轉成使用者友好的文字值。最後指派給<code>TextView</code>的text。轉換的邏輯非常簡單,就是把秒數轉為分鐘數,最後轉為小時和分鐘的值。分鐘和小時數如果大于1的時候機關就顯示為minutes和hours,等于1的時候為minute和hour。
現在就可以試試效果了。在Activity的<code>onCreate()</code>方法裡添加下面的代碼:
運作結果如下圖:

看起來還不錯吧。
如果我們能夠這個view添加一個方法來設定文本展示的模闆,就像設定duration一樣。但是,這個template其實并不會想duration一樣需要經常的設定,更多的是一個類似于常數一樣的存在。是以對于添加一個方法來說,添加一個XML屬性更加合适。
首先添加values/attrs.xml檔案,XML屬性就在這個檔案中定義。我們隻需要添加一個字元串類型的,名稱為template的屬性。添加之後attrs.xml檔案看起來是這樣的:
我們聲明了一個名稱為TemplateTextView的declare-styleable節點。名字可以任意起,不過最好還是在哪個view裡使用就叫做什麼。這裡叫做TemplateTextView是因為後面這個XML屬性會用與很多其他的自定義view中。來看看是怎麼使用這個屬性的。
在格式化代碼(快捷鍵Ctrl+Alt+L,或者Cmd+Alt+L)後在<code>LinearLayout</code>中會增加一行<code>xmlns:app="http://schemas.android.com/apk/res-auto"</code>這一句聲明了一個namespace,這樣APP就可以了解我們剛剛在自定義view的布局中添加的屬性了。當然需要使用這條聲明裡指定的app為字首:<code>app:template="%s was spent running"</code>。
現在就需要我們在代碼裡讀取并應用新添加的屬性值了。首先添加一個<code>var template:String? = null</code>的屬性,準備接收解析的字元串模闆。
第一行使用了<code>AttributeSet</code>類型的參數<code>attributeSet</code>,這個參數包含了在attrs.xml檔案中定義的全部的屬性。 方法<code>obtainStyledAttributes()</code>主要做了兩件事:
過濾全部的自定義屬性,并把這些屬性的定義和給定的值關聯起來。
傳回你在第二個參數所指定的屬性組合。
<code>R.styleable.TemplateTextView</code>就是我們自己定義的屬性數組,這裡隻有一個元素。<code>R.styleable.TemplateTextView_template</code>是我們自定義屬性數組裡的那個叫做template的元素。然後我們使用typed array來擷取這個屬性的值。如果沒有設定模闆,或者模闆中不包含處理字元串的%s的話就是用我們之前定義的預設的文字模闆來代替。
但是有一點需要格外注意:不管有沒有擷取到屬性值,都要回收TypedArray對象,<code>attributes.recycle()</code>。
上下兩個分别設定了不同的template,中間的不設定,運作一下看看修改後的效果如何:
對于大多數的Android視圖XML屬性都有對應的方法來通過代碼的方式設定對應的值。對于自定義視圖是否需要這麼做,主要取決于你打算怎麼用。添加一個方法也沒什麼問題。
下一篇主要簡述如何繪制視圖的内容,并自定義一個顯示折線圖的視圖。
歡迎加群互相學習,共同進步。QQ群:iOS: 58099570 | Android: 572064792 | Nodejs:329118122 做人要厚道,轉載請注明出處!
本文轉自張昺華-sky部落格園部落格,原文連結:http://www.cnblogs.com/sunshine-anycall/p/5448108.html,如需轉載請自行聯系原作者