標籤:
1、設定當前View自訂屬性需要在res的values檔案夾下建立個attrs檔案,在attrs檔案中設定相關的自訂屬性設定自訂屬性的名稱
<!-- format屬性可以用來限制當前自訂的屬性是什麼類型, 中間可以用 | 來串連,表示可以支援多種類型 --><attr name="user_defined_attribute" format="color" /> <!-- 可以指定枚舉類型,用來自訂一些需要使用者選擇的屬性, 比如android系統中的android:visibility屬性 --><attr name="user_defined_attribute1" format="enum"> <enum name="type_0" value="0" /> <enum name="type_1" value="1" /></attr>
定義這些屬性所屬於的 declare-styleable
<declare-styleable name="MyViewStyleable"> <attr name = "user_defined_attribute"/> <attr name = "user_defined_attribute1"/></declare-styleable>
2、繼承相關的view,在構造方法中擷取相關的屬性
自訂view通常優先考慮系統有沒有合適的view來使用,如果有的話應該先繼承系統已有的view進行擴充,如果系統沒有類似的View在自訂對應的View
public CustomVolumControlBar(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); TypedArray a = context.getTheme(). obtainStyledAttributes(attrs, R.styleable. MyViewStyleable, defStyleAttr, 0); int n = a.getIndexCount(); for (int i = 0; i < n; i++) { int index = a.getIndex(i); switch (index) { case R.styleable. MyViewStyleable_user_defined_attribute: mAttribute = a.getInt(index, 20); break; case R.styleable. MyViewStyleable_user_defined_attribute1: mAttribute1= a.getInt(index, 0); break; } } a.recycle(); }
同時構造方法一般還會負責進行一些畫筆的初始化等工作。
3、在onMeasure(或onSizeChange)方法中為屬性賦值
這裡一般用來確定當前view的寬高,並根據寬高等計算一些座標預設的值。
通常這裡會用到如下的一些代碼:
//擷取當前的模式/** * MeasureSpec封裝了父布局傳遞給子布局的布局要求,每個MeasureSpec代表了一組寬度和高度的要求 * MeasureSpec由size和mode組成。 * 三種Mode: * 1.UNSPECIFIED * 父不沒有對子施加任何約束,子可以是任意大小(也就是未指定) * 沒有設定寬高時,模式為UNSPECIFIED * 2.EXACTLY * 父決定子的確切大小,子被限定在給定的邊界裡,忽略本身想要的大小。 * (當設定width或height為match_parent時,模式為EXACTLY,因為 * 子view會佔據剩餘容器的空間,所以它大小是確定的) * 3.AT_MOST * 子最大可以達到的指定大小 * (當設定為wrap_content時,模式為AT_MOST, 表示子view的大小最多是多少, * 這樣子view會根據這個上限來設定自己的尺寸) * * MeasureSpecs使用了二進位去減少對象的分配。 */ //可以簡單理解為://wrap_parent -> MeasureSpec.AT_MOST//match_parent -> MeasureSpec.EXACTLY//具體值 -> MeasureSpec.EXACTLYint heightMode = MeasureSpec.getMode(heightMeasureSpec);//擷取當前的高度int heightSize= MeasureSpec.getSize(heightMeasureSpec);// 根據所傳的值大小和模式建立一個合適的值heightMeasureSpec = MeasureSpec.makeMeasureSpec(exceptHeight, MeasureSpec.EXACTLY); //重新設定寬高setMeasuredDimension(wght, wght);
4、在onDraw方法中繪製相關的自訂view
此處需要擷取到當前的畫布,然後用對應的畫筆進行相關的繪製操作。通常會涉及到如下方法
//用來儲存Canvas的狀態save之後,可以調用Canvas的平移、放縮、旋轉、錯切、裁剪等操作canvas.save();//用來恢複Canvas之前儲存的狀態。防止save後對Canvas執行的操作對後續的繪製有影響canvas.restore();//save和restore要配對使用(restore可以比save少,但不能多),//如果restore調用次數比save多,會引發Error//上面兩個方法結合使用可以相當於把畫布分成多個圖層進行繪製,各個圖層間互不影響//移動座標原點到指定位置ccanvas.translate(x,y); //對畫布旋轉指定的角度canvas.rotate(30);
即使再複雜的View也是用Paint一次次繪製得出的。所以只要慢慢的調整畫筆,調整顏色,一個好的自訂view就會出現的。
5、重寫onTouchEvent方法(手勢控制相關)
一般用來檢測一些首飾相關的操作,用來和使用者進行互動。設計思路通常如下:
1.擷取使用者當前的點擊(觸摸、抬起)座標2.用單前座標和繪製好的View進行比較3.根據預先設定的邏輯,然後在對應的位置執行相關的操作。(如重繪或移動等)6、在xml檔案中使用1.全路徑名引用自訂控制項2.在自訂控制項中引入自訂屬性
如下列代碼所示:
<com.test.myview.view.MyTestView <!-- hwy為引用時使用的名字,可以隨意,res後面為AndroidManifest中的包名, 這行引用也可以在根布局中引入 --> xmlns:hwy="http://schemas.android.com/apk/res/com.test.myview" android:layout_width="match_parent" android:layout_height="match_parent" hwy: user_defined_attribute="#ffffffff" hwy: user_defined_attribute1="type_1"/>
Android自訂View的一般步驟