Android自訂控制項系列二:自訂開關按鈕(一),android控制項

來源:互聯網
上載者:User

Android自訂控制項系列二:自訂開關按鈕(一),android控制項

這一次我們將會實現一個完整純粹的自訂控制項,而不是像之前的群組控制項一樣,拿系統的控制項來實現;計劃分為三部分:自訂控制項的基本部分自訂控制項的觸摸事件的處理自訂控制項的自訂屬性

下面就開始第一部分的編寫,本次以一個定義的開關按鈕為例,下面就開始吧:


先看看效果,一個點擊開關按鈕,實現點擊切換開關狀態:



為了能夠講解清晰,還是來一些基本的介紹。

首先需要明確的就是自訂控制項還是繼承自View這個類,Google在View這個類裡面提供了相當多的方法供我們使用,使用這些方法我們可以實現相當多的效果和功能,在這裡需要用到幾個主要的方法;


自訂控制項的步驟、用到的主要方法:

1、首先需要定義一個類,繼承自View;對於繼承View的類,會需要實現至少一個構造方法;實際上這裡一共有三個構造方法:


public View (Context context)是在java代碼建立視圖的時候被調用(使用new的方式),如果是從xml填充的視圖,就不會調用這個


public View (Context context, AttributeSet attrs)這個是在xml建立但是沒有指定style的時候被調用


public View (Context context, AttributeSet attrs, int defStyle)這個是在第二個基礎上添加style的時候被調用的


所以對於這裡來說,如果不使用style, 我們重點關注第二個構造方法即可


2、對於任何一個控制項來說,它需要顯示在我們的介面上,那麼肯定需要定義它的大小;在這裡Google提供了一個方法:protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec);我們去看這個方法的內部,實際上是調用了protected final void setMeasuredDimension(int measuredWidth, int measuredHeight);這個方法,其中第一個參數是view的寬,第二個參數是view的高,這樣我們就可以設定view的寬高了,但是要注意,這樣設定的單位都是像素


3、對於一個需要顯示的控制項來說,我們往往還需要確定它的位置:這就要求重寫onLayout方法;但是實際上這個方法在自訂view的時候使用的不多,原因是因為對於位置來說,控制項只有建議權而沒有決定權,決定權一般在父控制項那裡。


4、對於一個控制項,需要顯示,我們當然需要將它繪製出來,這裡就需要重寫onDraw方法,來將這個控制項繪製出來


5、當控制項狀態改變的時候,我們很可能需要重新整理view的顯示狀態,這時候就需要調用invalidate()方法,這個方法實際上會重新調用onDraw方法來重繪控制項


6、在定義控制項的過程中,如果需要對view設定點擊事件,可以直接使用setOnClickListener方法,而不需要寫view.setOnClickListener;


7、在布局檔案中將這個自訂控制項定義出來,注意名字要使用全類名;而且,由於是繼承自view控制項,所以在xml檔案中如果是view本身的屬性都可以直接使用,比如:android:layout_width等等


這裡比較關鍵的地方就在於這個onDraw方法,我們一起來看一下:


/** * 畫view的方法,繪製當前view的內容 */@Overrideprotected void onDraw(Canvas canvas) {// super.onDraw(canvas);Paint paint = new Paint();// 開啟消除鋸齒paint.setAntiAlias(true);// 畫背景canvas.drawBitmap(backgroundBitmap, 0, 0, paint);// 畫滑塊canvas.drawBitmap(slideButton, slideBtn_left, 0, paint);}



onDraw方法傳入的參數是一個Canvas畫布對象,這個實際上跟Java中的差不太多,我們要在畫布上畫畫也需要一個畫筆,我們這裡也將其初始化出來Paint paint = new Paint(),同時設定了一個消除鋸齒效果paint.setAntiAlias(true),然後調用drawBitmap的方法,先後繪製了開關的背景和開關的滑塊,分別入:


                          


這裡要注意的一點就是,drawBitmap(Bitmap bitmap, float left, float top, Paint paint)方法中間的兩個float類型的參數,分別代表繪製圖形的左上方的x和y的座標(原點設定在左上方),所以這裡如果我們個繪製座標都傳入0,0,那麼開關會處在一個關的狀態,這裡,我們對於滑塊使用了一個變數slideBtn_left來設定其位置,那麼對於關閉狀態,slideBtn_left的值就應該為0,對於開啟狀態,slideBtn_left的值就應該是backgroundBitmap(背景)的寬度減去slideButton(滑塊)的寬度


那麼這樣一來,機制就比較清楚了,我們只需要在控制項上設定一個點擊事件,同時設定一個boolean變數代表開關的狀態,當點擊的時候,切換這個boolean類型的變數為true或者false,同時變化slideButton的值為0或者backgroundBitmap.getWidth()-slideButton.getWidth(),然後再調用invalidate()方法重新整理控制項,就可以實現基本的開關功能了


下面來看具體的代碼,註解比較詳細:


自訂控制項的類MyToggleButton.java,繼承自View:

package com.example.togglebutton.ui;import com.example.togglebutton.R;import android.content.Context;import android.graphics.Bitmap;import android.graphics.BitmapFactory;import android.graphics.Canvas;import android.graphics.Paint;import android.util.AttributeSet;import android.view.View;/* * 自訂view的幾個步驟: * 1、首先需要寫一個類來繼承自View * 2、需要得到view的對象,那麼需要重寫構造方法,其中一參的構造方法用於new,二參的構造方法用於xml布局檔案使用,三參的構造方法可以傳入一個樣式 * 3、需要設定view的大小,那麼需要重寫onMeasure方法 * 4、需要設定view的位置,那麼需要重寫onLayout方法,但是這個方法在自訂view的時候用的不多,原因主要在於view的位置主要是由父控制項來決定 * 5、需要繪製出所需要顯示的view,那麼需要重寫onDraw方法 * 6、當控制項狀態改變的時候,需要重繪view,那麼調用invalidate();方法,這個方法實際上會重新調用onDraw方法 * 7、在這其中,如果需要對view設定點擊事件,可以直接調用setOnClickListener方法 */public class MyToggleButton extends View {/** * 開關按鈕的背景 */private Bitmap backgroundBitmap;/** * 開關按鈕的滑動部分 */private Bitmap slideButton;/** * 滑動按鈕的左邊界 */private float slideBtn_left;/** * 當前開關的狀態 */private boolean currentState = false;/** * 在代碼裡面建立對象的時候,使用此構造方法 *  * @param context */public MyToggleButton(Context context) {super(context);}/** * 在布局檔案中聲明的view,建立時由系統自動調用 *  * @param context * @param attrs */public MyToggleButton(Context context, AttributeSet attrs) {super(context, attrs);initView();}/** * 測量尺寸時的回調方法 */@Overrideprotected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {// super.onMeasure(widthMeasureSpec, heightMeasureSpec);// 設定當前view的大小 width:view的寬,單位都是像素值 heigth:view的高,單位都是像素值setMeasuredDimension(backgroundBitmap.getWidth(),backgroundBitmap.getHeight());}// 這個方法對於自訂view的時候協助不大,因為view的位置一般由父組件來決定的@Overrideprotected void onLayout(boolean changed, int left, int top, int right,int bottom) {super.onLayout(changed, left, top, right, bottom);}/** * 畫view的方法,繪製當前view的內容 */@Overrideprotected void onDraw(Canvas canvas) {// super.onDraw(canvas);Paint paint = new Paint();// 開啟消除鋸齒paint.setAntiAlias(true);// 畫背景canvas.drawBitmap(backgroundBitmap, 0, 0, paint);// 畫滑塊canvas.drawBitmap(slideButton, slideBtn_left, 0, paint);}/** * 初始化view */private void initView() {backgroundBitmap = BitmapFactory.decodeResource(getResources(),R.drawable.switch_background);slideButton = BitmapFactory.decodeResource(getResources(),R.drawable.slide_button);/* * 點擊事件 */setOnClickListener(new OnClickListener() {@Overridepublic void onClick(View v) {currentState = !currentState;flushState();flushView();}});}/** * 重新整理視圖 */protected void flushView() {// 重新整理當前view會導致ondraw方法的執行invalidate();}/** * 重新整理當前的狀態 */protected void flushState() {if (currentState) {slideBtn_left = backgroundBitmap.getWidth()- slideButton.getWidth();} else {slideBtn_left = 0;}}}


在布局檔案中將其定義出來:


<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"    tools:context="${relativePackage}.${activityClass}" >    <com.example.togglebutton.ui.MyToggleButton        android:id="@+id/my_toggle_btn"        android:layout_width="wrap_content"        android:layout_height="wrap_content"        android:layout_centerInParent="true" /></RelativeLayout>


在這裡由於沒有寫任何點擊觸發業務的邏輯,只是一個單純的控制項,所以在MainActivity裡面沒有加入多的代碼:


package com.example.togglebutton;import android.app.Activity;import android.os.Bundle;public class MainActivity extends Activity {@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);}}


至此一個自訂的開關按鈕就完成了,後面兩篇將會介紹如何在上面實現 點擊拖動開關的效果 和如何?自訂屬性,謝謝支援!


android自訂控制項

控制項都屬於View類
有可見度屬性:VISIBLE,INVISIBLE,GONE
你可以調setVisibility方法,比如
TextView txt;
txt.setVisibility( View.GONE );//然後控制項就不見了!
txt.setVisibility( View.VISIBLE );//然後控制項又出現了!

或者有一個ViewStub的控制項,可以實現動態載入布局檔案。
可能不太適合你的問題。具體怎麼用自己在搜一下吧

希望對你有協助
 
android自訂控制項的時需要重寫什方法,怎判斷

重寫兩個構造方法 就可以啦
 

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.