當android現有的控件不能滿足我們的需求的時候,我們一般要自定義自己的控件。
自定義控件的實現並不特別難,關鍵在理解需求及注意實現的細節。
現在舉個例子實現開關按鈕的自定義控件。
需求:
1.點擊按鈕,切換開關狀態。
2.拖動按鈕,切換開關狀態。
注意細節問題:
1.用戶拖動控件的時候,有點擊屏幕的事件,這個時候註冊監聽點擊事件會被響應。說白了就是拖動和點擊混淆了。
即用戶明明想拖動的,你卻實現了拖動完成+點擊。
2.拖動是超越邊界。
3.拖動到中途停止拖動,狀態無法選擇。
解決問題方法:
1.用戶拖動控件的距離超過5,認爲用戶意圖是拖動,禁用點擊功能;否則,認爲用戶是點擊意圖,實現點擊功能。
2.拖動位置小於最小位置,設置爲0;超過最大位置,設置爲最大邊界。
3.拖動到中途的位置與中線(昨天起始位置與最大位置的中線)比較,小於中線歸爲起始狀態,大於或等於中線爲截止的狀態。
@Override
/**
* 測量尺寸時的回調方法 這個方法我以前比較少用所以這裏mark
*/
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
//super.onMeasure(widthMeasureSpec, heightMeasureSpec);
/**
* 設置當前view的大小
* width :view的寬度
* height :view的高度 (單位:像素)
*/
setMeasuredDimension(backgroundBitmap.getWidth(),backgroundBitmap.getHeight());
}
加上自定義屬性(常用於封裝組件給自己或他人使用)
首先在res/values/attrs.xml設置
<?xml version="1.0" encoding="utf-8"?>
<resources>
<!-- 聲名屬性集的名稱 -->
<declare-styleable name="MySwitchBtn">
<!-- 聲名一個屬性 name是my_background(開關背景圖) 類型爲 引用類型 引用資源ID -->
<attr name="my_background" format="reference" />
<!-- 聲名一個屬性 name是my_slide_btn(開關按鈕圖) 類型爲 引用類型 引用資源ID -->
<attr name="my_slide_btn" format="reference" />
<!-- 聲名一個屬性 name是curr_state (初始開關狀態) 類型爲 boolean 類型-->
<attr name="curr_state" format="boolean" />
</declare-styleable>
</resources>
在自定義控件類中解析自定義屬性
MySwitchBtn.java
//獲得自定義的屬性
TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.MySwitchBtn);
//獲取自定義屬性個數
int N = ta.getIndexCount();
for (int i = 0; i < N; i++) {
<span style="white-space:pre"> </span>/*
<span style="white-space:pre"> </span> * 獲得某個屬性的ID值
<span style="white-space:pre"> </span> */
<span style="white-space:pre"> </span>int itemId = ta.getIndex(i);
<span style="white-space:pre"> </span>switch (itemId) {
<span style="white-space:pre"> </span>case R.styleable.MySwitchBtn_curr_state:
<span style="white-space:pre"> </span>currState = ta.getBoolean(itemId, false);//獲取自定義屬性value
<span style="white-space:pre"> </span>
<span style="white-space:pre"> </span>break;
<span style="white-space:pre"> </span>case R.styleable.<span style="font-family: Arial, Helvetica, sans-serif;">MySwitchBtn</span><span style="font-family: Arial, Helvetica, sans-serif;">_my_background:</span>
<span style="white-space:pre"> </span>backgroundId = ta.getResourceId(itemId, -1);//獲取背景圖片的id
<span style="white-space:pre"> </span>if(backgroundId == -1){
<span style="white-space:pre"> </span>throw new RuntimeException("請設置背景圖片");
<span style="white-space:pre"> </span>}
<span style="white-space:pre"> </span>backgroundBitmap = BitmapFactory.decodeResource(getResources(), backgroundId);
<span style="white-space:pre"> </span>
<span style="white-space:pre"> </span>break;
<span style="white-space:pre"> </span>case R.styleable.MySwitchBtn_my_slide_btn:
<span style="white-space:pre"> </span>slideBtnId = ta.getResourceId(itemId, -1);//獲取開關圖片的id
<span style="white-space:pre"> </span><span style="font-family: Arial, Helvetica, sans-serif;">if(</span><span style="font-family: Arial, Helvetica, sans-serif;">slideBtnId </span><span style="font-family: Arial, Helvetica, sans-serif;">== -1){</span><span style="white-space:pre"></span><pre name="code" class="java"><span> </span>throw new RuntimeException("請設置背景圖片");
<span> </span>}
slideBtn = BitmapFactory.decodeResource(getResources(), slideBtnId);
break;
default:
break;
}
}
這樣的話我們就完成了這三個自定義控件屬性的定義及獲取解析。