SwitchButton 開關按鈕 的多種實現方式


剛開始接觸開關樣式的按鈕是在IOS系統上面,它的切換以及滑動十分帥氣,深入人心。

所謂的開關按鈕,就是只有2個狀態:on和off,下圖就是系統IOS 7上開關按鈕效果。

起初我在android上我只會使用CheckBox去滿足對應的功能。后來,查看開發文檔發現,android也有了自己的原生態開關控件,並且在4.0版本中又優化加入了新的類似控件--Switch控件,以及使用起來十分簡單的ToggleButton,可是它們只是帶有切換效果,而不帶有滑動切換效果,並且Switch控件只支持高版本的系統,對於2.3就不支持。所以,要想看如何實現滑動切換的效果,必須了解這些控件的實現方式。下面,讓我們查看下android開發文檔,看看這些是如何實現使用的。

 

注意:本文中涉及到自定義控件 並自定義配置屬性declare-styleable,

如果你對於自定義控件的自定義配置屬性還不是很了解可以看:android 自定義控件 使用declare-styleable進行配置屬性(源碼角度)

 

查看查看開發文檔:

 

CompoundButton

extends Button
implements Checkable

 

java.lang.Object

android.view.View

 

android.widget.TextView

 

 

android.widget.Button

 

 

 

android.widget.CompoundButton

 

Known Direct Subclasses

CheckBox,RadioButton,Switch,ToggleButton

以上4類都是開關類型切換的控件,它們的父類都是CompoundButton。

 

 

 它對應的方法和類有:

 

點擊選擇監聽接口。

Nested Classes

interface

CompoundButton.OnCheckedChangeListener

Interface definition for a callback to be invoked when the checked state of a compound button changed.

 

返回左右填充的VIEW,加上間隔

Public Methods

int

getCompoundPaddingLeft()Returns the left padding of the view, plus space for the left Drawable if any.

int

getCompoundPaddingRight()Returns the right padding of the view, plus space for the right Drawable if any.

 

boolean:是否被選中。

boolean

isChecked()

 

設置Button的Drawable屬性

void

setButtonDrawable(int resid)Set the background to a given Drawable, identified by its resource id.

 

設置是否選中

void

setChecked(boolean checked)Changes the checked state of this button.

 

改變當前的狀態,true-->false  ;false-->true

void

toggle()Change the checked state of the view to the inverse of its current state

 

控件全局 繪制

void

onDraw(Canvas canvas)Implement this to do your drawing.

 protected void onDraw (Canvas canvas)

         實現你自己的繪制。

                   參數

                            canvas    在畫布上繪制背景

   protected boolean verifyDrawable (Drawable who)

         如果你的視圖子類顯示他自己的可視化對象,他將要重寫此方法並且為了顯示可繪制返回true。此操作允許進行繪制時有動畫效果。

  確認當重寫從方法時,需調用父類相應方法。

                   參數

                            who         需判斷的可繪制對象(Drawable)。如果是你要顯示的對象,返回True,否則返回調用父類的結果。

                   返回值

                           boolean 如果可繪制對象(Drawable)已經在視圖中顯示,返回True否則返回false。並且此處不允許使用動畫。

 

 

下面讓我們來看看如何實現這個效果把:

 

一.使用ToggleButton控件實現:

使用ToggleButton控件十分方便,你可以看作他為一個CheckBox,只用設置它的button、background等幾個屬性即可。

首先:res--創建drawable文件夾 -- 創建switch_btn.xml資源文件--作以下配置

 

[html]  view plain copy
 
  1. <?xml version="1.0" encoding="utf-8"?>  
  2. <selector  
  3.   xmlns:android="http://schemas.android.com/apk/res/android">  
  4.     <item android:state_checked="true" android:drawable="@drawable/ios7_switch_on" />  
  5.     <item android:drawable="@drawable/ios7_switch_off" />  
  6. </selector>  

其中:android:state_checked="true" 表示選中on時候的,效果為:android:drawable="@drawable/ios7_switch_on" 

 

     反之就是未選中off情況下的效果:android:drawable="@drawable/ios7_switch_off"

之后在布局文件中寫控件:

 

[html]  view plain copy
 
  1. <ToggleButton  
  2.         android:id="@+id/mTogBtn"  
  3.         android:layout_width="wrap_content"  
  4.         android:layout_height="wrap_content"  
  5.         android:layout_gravity="center_horizontal"  
  6.         android:background="@android:color/transparent"  
  7.         android:button="@drawable/toggle_btn"  
  8.         android:checked="false"  
  9.         android:text=""  
  10.         android:textOff=""  
  11.         android:textOn="" />  

這里的    

 

android:textOn=""   表示:選中情況下顯示的文本

android:textOff=""   表示:未選中情況下顯示的文本

android:checked="false"  表示:初始化時候,默認是未選中的

android:button="@drawable/toggle_btn"  表示:button樣式

android:background="@android:color/transparent"  表示:背景,這里不用它的默認背景,所以設置為透明

之后在主程序中實例化,並設置checked點擊監聽

 

[java]  view plain copy
 
  1. ToggleButton mTogBtn = (ToggleButton) findViewById(R.id.mTogBtn); // 獲取到控件  
  2. mTogBtn.setOnCheckedChangeListener(new OnCheckedChangeListener() {  
  3.   
  4.     @Override  
  5.     public void onCheckedChanged(CompoundButton buttonView,boolean isChecked) {  
  6.         // TODO Auto-generated method stub  
  7.         if(isChecked){  
  8.             //選中  
  9.         }else{  
  10.             //未選中  
  11.         }  
  12.     }  
  13. });// 添加監聽事件  

這樣ToggleButton的開關切換就輕松實現了。

 

二.重寫CompoundButton控件實現帶滑動效果的開關按鈕:

    重寫CompuundButton的實現可能會顯得相對繁瑣些,主要是考慮狀態是否已經選中等情況的文字顯示。

    可以查看官方文檔,之后繼承CompuundButton,在布局的動畫和顯示上調用onDraw(Canvas canvas)重畫既可以,如果想要加入拖動屬性,那么在該VIEW內重寫觸摸事件onTouchEvent(MotionEvent ev)在里面判斷拖動距離,之后根據拖動情況判斷開關是on還是off。

    由於繼承的是CompoundButton,所以里面的監聽方法,setChecked等方法都是自帶的,繼承下來寫操作就可以了,不用自己在去加判斷什么的屬性了。

    由於DEMO中的繼承CompoundButton的SwitchButton是使用自定義配置的,所以如果不了解自定義配置的可以看以下文章:android 自定義控件 使用declare-styleable進行配置屬性(源碼角度)

    具體的這邊不貼代碼了,可以查看DEMO里面的,都有注釋。

 

三.重寫CheckBox控件實現帶滑動效果的開關按鈕:

    其實,看上面給的開發文檔內容,大家都可以知道,CheckBox其實就是繼承CompoundButton控件的,只是重構CheckBox會比CompoundButton方便好多,里面的很多方法都是寫好的,只要自己去判斷觸摸事件onTouchEvent(MotionEvent ev),以及onDraw(Canvas canvas)重畫就可以。這里DEMO中使用到的是第3放庫內的一個控件,大致操作和上面其實大同小異。

 

四.重寫View實現帶滑動效果的開關按鈕:

   眾所周知,以上所有的控件都是繼承了View這個父類,所以,如果你用View去操作的話,就沒有自帶方法的限制,可是要滿足你要 實現的SwitchButton效果,你必須自己寫開關狀態監聽接口,並且自己寫setChecked方法實現同等的效果。在優化方面要自己多加細心考慮。其他操作與以上控件的重構大同小異。

    注意:由於狀態切換等,enabled屬性改變等,是你自定義的方法內的話,你必須自己去調用invalidate();方法,去讓UI判斷是否有更改並做出相應的變化。

例如:

 

[java]  view plain copy
 
  1. @Override  
  2. public void setEnabled(boolean enabled) {  
  3.     // TODO Auto-generated method stub  
  4.     mEnabled = enabled;  
  5.     mAlpha = enabled ? MAX_ALPHA : MAX_ALPHA/2;  
  6.     Log.d("enabled",enabled ? "true""false");  
  7.     super.setEnabled(enabled);  
  8.     invalidate();  
  9. }  
  10.   
  11. /** 自動判斷切換至相反的屬性 : true -->false ;false -->true */  
  12. public void toggle() {  
  13.     setChecked(!mSwitchOn);  
  14. }  
  15.   
  16.    /** 設置選中的狀態(選中:true   非選中: false) */  
  17.    public void setChecked(boolean checked) {  
  18.     mSwitchOn = checked;  
  19.        invalidate();  
  20.    }  

還有,你如果是自定義的VIEW,你在里面設置了enabled屬性,你必須在onTouchEvent(MotionEvent event)觸摸操作的時候判斷你所設置的enabled屬性是否為true,是的話就可以相應點擊事件,否則的話你要屏蔽掉點擊事件。因為你自定義的view中的enabled屬性並不知道他設定后會達到什么效果,這些都是要注意的點。

 

還有就是要設置接口監聽狀態變化:

 

[java]  view plain copy
 
  1. /**  
  2.  * 設置 switch 狀態監聽  
  3.  * */  
  4. public void setOnChangeListener(OnSwitchChangedListener listener) {  
  5.     switchListener = listener;  
  6. }  
  7. /**  
  8.  * switch 開關監聽接口 
  9.  *  */  
  10. public interface OnSwitchChangedListener{  
  11.     public void onSwitchChange(SlideSwitchView switchView, boolean isChecked);  
  12. }  

 

 

有的人可能會希望有SwitchButton在enabled設置為false的時候,SwitchButton不能點擊且要改變顏色,使他看過去是不能點擊的。你可以進行如下操作(在學習別的人代碼中得到的提示,學以致用):

先初始化透明度:255為不透明

 

[java]  view plain copy
 
  1. /** 最大透明度,就是不透明 */  
  2. private final int MAX_ALPHA = 255;  
  3. /** 當前透明度,這里主要用於如果控件的enable屬性為false時候設置半透明 ,即不可以點擊 */  
  4. private int mAlpha = MAX_ALPHA;  

之后重寫setEnabled方法,通過這個方法判斷enabled屬性值

 

 

[java]  view plain copy
 
  1. @Override  
  2. public void setEnabled(boolean enabled) {  
  3.     // TODO Auto-generated method stub  
  4.     mEnabled = enabled;  
  5.     mAlpha = enabled ? MAX_ALPHA : MAX_ALPHA/2;  
  6.     super.setEnabled(enabled);  
  7.     invalidate();  
  8. }  

如果改變了enabled屬性,系統便會查看UI是否需要變化,之后在UI方法onDraw(Canvas canvas)中調用:

 

 

[java]  view plain copy
 
  1. android.graphics.Canvas.saveLayerAlpha(RectF bounds, int alpha, int saveFlags)  

方法,其中的第2個屬性alpha就是透明度,之后便可以實現相應的效果。

 

 

由於目前對於重寫VIEW的onDraw方法的了解不是很深入,所以這里的DEMO中的幾個方法都是查看網絡之后加上自己的優化和注釋演變過來,等這一塊深入了后在重寫寫一篇關於這個的感受和使用說明。由於可能理解不是很深刻,如果有什么不足之處可以提出,謝謝。

 

最后讓我們來看看效果如何,上圖:

                      

 

 

最后上源碼DEMO:下載地址

原文:http://blog.csdn.net/vipzjyno1/article/details/23707149


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM