編輯:關於Android編程
我們在自定義android組件的時候,除了用Java構建出組件的樣子外,有時候還需要去申明一些“屬性”提供給項目使用,那麼什麼是組件的屬性呢?
例如在清單文件中,創建一個TextView的時候,這是需要制定TextView的android:layout_width=wrap_content android:layout_height=wrap_content等等這些都是組件的屬性,TextView是android系統為我們提供好的組件,它的屬性亦是android系統為我們提供了。詳情查看android的源碼,我這裡舉例android2.3的源碼,路徑是所有的format類型// 聲名屬性集的名稱,即這些屬性是屬於哪個控件的。 // 聲名屬性 current_state 格式為 boolean 類型 // 聲名屬性 slide_button格式為 reference 類型
com.example.mytogglebtn 此應用的包名,如manifest配置文件中一致。
布局文件:
三、在代碼中對屬性進行解析,代碼如下:
TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.MyToggleBtn);// 由attrs 獲得 TypeArray
以上是創建自定義屬性的大致步驟。下面,我將要創建一個自定義控件的Demo,來學習學習自定義屬性的相關知識點。
首先,需要創建一個自定義控件出來,並且繼承View。在工程的res/values文件夾下創建attrs.xml文件:
然後在布局文件中,引用這個自定義控件MyView
由於創建出來的自定義組件MyView是繼承於View的,所以必須得復寫View的構造方法,View中有三個構造方法,先來看看復寫帶一個參數的構造方法:
package com.example.myattrs; import android.content.Context; import android.view.View; public class MyView extends View { public MyView(Context context) { super(context); // TODO Auto-generated constructor stub } }運行一下工程,那麼工程立即崩潰了,報錯也很清晰明了:
09-17 06:52:24.389: E/AndroidRuntime(1563): Caused by: java.lang.NoSuchMethodException:
表示沒有找到某個帶兩個參數的構造方法,於是,知道自定義屬性必須得復寫父類的另外一個構造方法,修改如下:
package com.example.myattrs; import android.content.Context; import android.util.AttributeSet; import android.view.View; public class MyView extends View { public MyView(Context context, AttributeSet attrs) { super(context, attrs); int count = attrs.getAttributeCount(); for (int index = 0; index < count; index++) { String attributeName = attrs.getAttributeName(index); String attributeValue = attrs.getAttributeValue(index); System.out.println(name: + attributeName + value: + attributeValue); } } }打印結果如下:
AttributeSet:對布局文件XML解析後的結果,封裝為AttributeSet對象。存儲的都是原始數據,但是對數據進行了簡單的加工。
由此構造器幫我們返回了布局文件XML的解析結果,拿到這個結果,我們該怎麼做呢?接下來,我們來看看View類對於這個是怎麼處理的:
public View(Context context, AttributeSet attrs) { this(context, attrs, 0); }
public View(Context context, AttributeSet attrs, int defStyle) { this(context); TypedArray a = context.obtainStyledAttributes(attrs, com.android.internal.R.styleable.View, defStyle, 0);於是,找到一個跟屬性很相關的類TypeArray,那麼接下來,我在自定義控件的構造方法上也獲取一下TypeArray這個類:
翻看一下TypeArray的源碼會發現,TypeArray是不繼承任何類(除了Object)的,也就是說,TypeArray相當於一個工具類,通過context.obtainStyledAttributes方法,將AttributeSet和屬性的類型傳遞進去,比如AttributeSet相當於原材料,屬性類型相當於圖紙,context.obtainStyledAttributes相當於加工廠加工成所對象的屬性,封裝到TypeArray這個類裡。
package com.example.myattrs; import android.content.Context; import android.content.res.TypedArray; import android.util.AttributeSet; import android.view.View; public class MyView extends View { public MyView(Context context, AttributeSet attrs) { super(context, attrs); TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.MyView); int count = ta.getIndexCount(); for (int i = 0; i < count; i++) { int itemId = ta.getIndex(i); System.out.println(itemId:: + itemId); // 獲取屬性在R.java文件中的id switch (itemId) { case R.styleable.MyView_test_bitmap: int bitmapId = ta.getResourceId(itemId, 100); System.out.println(bitmapId:: + bitmapId); break; case R.styleable.MyView_test_id: int test_id = ta.getInteger(itemId, 10); System.out.println(test_id + test_id); break; case R.styleable.MyView_test_msg: String test_msg = ta.getString(itemId); System.out.println(test_msg:: + test_msg); break; default: break; } } } }
以下是TypeArray類裡的方法,這裡不寫注釋了,見名知意:
當在構造方法中獲取到這些設置好的屬性值時,取出其值,就可以在代碼中進行處理了。
上篇博客提到了Android自定義控件——仿ios的滑動開關按鈕,接下來,就要為這個滑動開關按鈕條件自定義的屬性,不熟悉上篇博客Demo的,可以先去浏覽器一下我的上篇博客,點這裡Android自定義控件——仿ios滑動開關按鈕
首先,按照上面介紹的步驟,先在res/values目錄下創建一個屬性文件attrs.xml:
然後,在引用自定義控件的布局文件acticity_main.xml上設置自定義屬性,記住,引用這些屬性之前,必須先引用命名空間:
xmlns:mytogglebtn=http://schemas.android.com/apk/res/com.example.slidebutton
其中:mytogglebtn 是任意取名,沒有強制要求,但是在控件中引用屬性的時候,要保持一致,不要寫錯了
com.example.slidebutton 是工程的包名,千萬不要弄錯了,不然找不到屬性文件
有了上面的步驟,我們就可以自定義組件類的構造方法中,將屬性集解析成TypeArray了,從TypeArray中獲取相關的屬性值,並用於初始化自定義控,以下是主要代碼:
public SlideButton(Context context, AttributeSet attrs) { super(context, attrs); // 獲得自定義屬性 TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.MyToggleBtn); int count = ta.getIndexCount(); for (int i = 0; i < count; i++) { int itemId = ta.getIndex(i); // 獲取某個屬性的Id值 switch (itemId) { case R.styleable.MyToggleBtn_currState: // 設置當前按鈕的狀態 currentState = ta.getBoolean(itemId, false); break; case R.styleable.MyToggleBtn_switchBG: // 設置按鈕的背景圖 int backgroundId = ta.getResourceId(itemId, -1); if (backgroundId == -1) throw new RuntimeException(資源沒有被找到,請設置背景圖); switchBG = BitmapFactory.decodeResource(getResources(), backgroundId); break; case R.styleable.MyToggleBtn_slideBg: // 設置按鈕圖片 int slideId = ta.getResourceId(itemId, -1); if (slideId == -1) throw new RuntimeException(資源沒有找到,請設置按鈕圖片); slideButtonBG = BitmapFactory.decodeResource(getResources(), slideId); break; default: break; } } }
從上可以看到,自定義屬性其實很簡單。就是在構造方法中,將獲取到的屬性集加工成TypeArray對象,通過這個對象取出屬性的id,通過id取出每個屬性對應的值(畢竟Android下的布局文件XML也是key-value形式的),最後將獲取到的屬性值(控件用戶自定義的數據)初始化到自定義控件上,這樣,一個完整的自定義控件就完成。這種完整的自定義控件方式用的並不多見,因為在開發自定義控件時候,需要什麼數據就直接在Java代碼裡設置就好了,方便多了。但是在特定的場合下,如果開發的控件某些數據不確定,或者所開發控件需要提供給其他人進行偏好設置什麼的,這種自定義屬性就顯得非用不可了。
源碼請在這裡下載
微信群是我們經常聊天聊工作的地方,但是你需要離開的時候想要將這個微信群轉給一個人來管理該怎麼辦呢?那麼微信群怎麼轉讓群主呢?微信群怎麼轉讓給別人?微信群怎麼
1.采用PUSCH跳頻時需要注意的問題在上行子幀中,PUCCH信道處於帶寬的高低兩側,或者說位於頻帶的邊緣,PUSCH信道則位於帶寬的中間。PUCCH信道也以RB對為基本
在android應用中,多屏滑動是一種很常見的風格,沒有采用viewpager的代碼實現會很長,如果采用ViewPager,代碼就會短很多,但是使用ViewPager也有
HttpURLConnection 拋出異常 Http的URL鏈接, 會發生錯誤, 主要原因是 在主UI線程中, 使用網絡調用(network call),