1. 程式人生 > >Android應用之——自己定義控件ToggleButton

Android應用之——自己定義控件ToggleButton

dimens 方法 true out con south bool action mov

我們經常會看到非常多優秀的app上面都有一些非常美麗的控件,用戶體驗非常好。比方togglebutton就是一個非常好的樣例,IOS系統以下那個精致的togglebutton現在在android以下也能夠實現了,並且還能夠自己定義它的顏色文字背景圖,做出各種美麗的開關按鍵出來。

這裏就用到了android裏面一個比較經常使用的技術——自己定義控件。


先來看下我們實現的自己定義的togglebutton效果圖:

技術分享 技術分享


自己定義控件的步驟:

1、首先,定義一個類繼承View 或者View的子類,這個取決於要定義的控件的類型。本例中,繼承自View。


2、繼承了View後 就須要重寫構造函數,有三個方法,各自是

	public MyView(Context context) {
		super(context);
		// TODO Auto-generated constructor stub
	}

	public MyView(Context context, AttributeSet attrs, int defStyleAttr) {
		super(context, attrs, defStyleAttr);
		// TODO Auto-generated constructor stub
	}

	public MyView(Context context, AttributeSet attrs) {
		super(context, attrs);
		// TODO Auto-generated constructor stub
這三個方法。依據不同的情況來使用,假設自己定義的控件須要設置xml屬性那麽就要用到第三個構造函數。假設須要設置xml屬性而且定義樣式,那麽就須要實現第二個構造函數,使用其第三個參數defStyleAttr,假設沒有以上兩點要求,那麽直接重寫第一個構造函數就可以。


這這個demo中,我們實現第一個構造函數就可以

	public ToggleButton(Context context, AttributeSet attrs) {
		super(context, attrs);

		initBitmap();//初始化bitmap
	}
重寫構造函數後,接下來就要依據不同控件的要求來選擇是否重寫onDraw和onMeasure方法了。

假設自己定義控件的大小是須要自己定義的,比方本例中的togglebutton,那麽首先須要重寫onMeasure方法,測算出自己定義控件的寬和高。

非常明顯,我們這個togglebutton的寬和高是非常easy得出來的,高度就是這個控件背景圖的寬和高

技術分享 技術分享

所以onMeasure方法重寫例如以下,得到自己定義控件的寬和高

	/**
	 * 初始化開關圖片
	 */
	private void initBitmap() {
		background = BitmapFactory.decodeResource(getResources(),
				R.drawable.switch_background);
		slideBackground = BitmapFactory.decodeResource(getResources(),
				R.drawable.slide_button_background);
	}

	/**
	 * 設置當前控件的寬和高
	 */
	@Override
	protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
		super.onMeasure(widthMeasureSpec, heightMeasureSpec);

		// 設置開關的寬和高
		setMeasuredDimension(background.getWidth(), background.getHeight());
	}

得到寬和高後,就須要繪制這個控件了。利用View的onDraw方法

重寫onDraw方法,我們能夠得到一個參數canvas

void onDraw(Canvas canvas)
有了這個canvas對象,就能夠非常方面的繪制出控件的樣子

先繪制控件的背景,由於togglebutton。事實上就是一個button在一個背景圖上面來回滑動產生不同的效果。所以我們先繪制它的背景。

canvas.drawBitmap(background, 0, 0, null);
繪制完背景後,就要繪制小滑塊了。小滑塊有兩種狀態,一種是在滑動,還有一種是精巧狀態,這兩種狀態我們須要分別進行處理。

當小滑塊在滑動的時候,背景圖是不會變的,並且它滑動到某個時刻的樣子也非常明白。滑動了多少距離就繪制它在某距離的狀態。可是有一種情況須要進行處理,那就是滑塊滑出邊界的情況,假設是從左邊滑出邊界,那麽就應該將它離左邊的距離置為0,也就是不讓它繼續滑動,同理右邊也要進行對應的處理。

滑動過程代碼例如以下:

if(isSliding) {		// 正在滑動中
			int left = currentX - slideBackground.getWidth() / 2;
			
			if(left < 0) {		// 當前超出了左邊界, 賦值為0
				left = 0;
			} else if(left > (background.getWidth() - slideBackground.getWidth())) {
				// 當前超出了右邊界, 賦值為: 背景的寬度 - 滑動塊的寬度
				left = background.getWidth() - slideBackground.getWidth();
			}
			
			canvas.drawBitmap(slideBackground, left, 0, null);
		}
精巧狀態的話,非常easy,依據不同的狀態將滑塊放置到控件的左邊和右邊就可以

if(currentState) {
				// 繪制開的狀態
				canvas.drawBitmap(slideBackground, 0, 0, null);
			} else {
				// 繪制關的狀態
				int left = background.getWidth() - slideBackground.getWidth();
				canvas.drawBitmap(slideBackground, left, 0, null);
			}

上面,我們就完畢了自己定義一個togglebutton的界面上的操作了,可是togglebutton的作用是用來控制開關的。所以還要對它的一些事件進行處理。

滑動事件的處理。捕獲用戶的操作。為它設置一個自己定義的狀態改變監聽器

/**
	 * 捕獲用戶操作的事件
	 */
	@Override
	public boolean onTouchEvent(MotionEvent event) {
		switch (event.getAction()) {
		case MotionEvent.ACTION_DOWN:
			currentX = (int) event.getX();
			isSliding = true;
			break;
		case MotionEvent.ACTION_MOVE:
			currentX = (int) event.getX();
			break;
		case MotionEvent.ACTION_UP:
			isSliding = false;
			currentX = (int) event.getX();

			int center = background.getWidth() / 2;

			// 當前最新的狀態
			boolean state = currentX < center;
			// 假設兩個狀態不一樣而且監聽事件不為null
			if (currentState != state && mOnToggleStateChangeListener != null) {
				// 調用用戶的回調事件
				mOnToggleStateChangeListener.onToggleStateChange(state);
			}
			currentState = state;
			break;
		default:
			break;
		}
		invalidate(); // 此方法被調用會使onDraw方法重繪
		return true;
	}


這裏自己定義了一個狀態改變監聽器。用來監聽togglebutton的狀態改變,然後回調方法,進行對應的處理。

public interface OnToggleStateChangeListener {

	void onToggleStateChange(boolean state);

}



最後。為這個控件提供三個方法,設置狀態為開或關的方法。另一個設置監聽事件的方法

/**
	 * 設置開關的狀態
	 * 
	 * @param state
	 */
	public void setToggleState(boolean state) {
		currentState = state;
	}

	public boolean getToogleState() {
		return currentState;
	}

	public void setOnToggleStateChangeListener(
			OnToggleStateChangeListener listener) {
		mOnToggleStateChangeListener = listener;
	}


到這裏,整個自定義togglebutton的過程就算完了。接下來我們就能夠在程序中使用自定義的控件了。

在xml文件裏,用全路徑名使用自己定義控件,然後在java代碼中就能夠獲取到這個自己定義控件的對象 和相關的方法了

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent" >

    <com.yang.togglebutton.ToggleButton
        android:id="@+id/togglebutton"
        android:layout_width="wrap_content"
        android:layout_height="30dip"
        android:layout_centerInParent="true" />

    <com.yang.togglebutton.ToggleButtonVIPS
        android:id="@+id/toggle2"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_below="@+id/togglebutton"
        android:layout_centerHorizontal="true" />

</RelativeLayout>


總結一下事實上就是幾個步驟:

1、繼承View或者它的子類,依據不同的情況重寫不同的構造函數(必須)

2、重寫onMeasure方法,測量控件的大小(非必須)

3、重寫onDraw方法,繪制控件(非必須)
4、為控件設置一些自己定義方法和監聽器(非必須)

5、在xml中使用。或者直接在java代碼中使用


轉載請註明出處http://blog.csdn.net/csr_yang/article/details/37341221




Demo下載




Android應用之——自己定義控件ToggleButton