-
剛開始接觸開關樣式的按鈕是在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資源文件--作以下配置
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>
反之就是未選中off情況下的效果:android:drawable="@drawable/ios7_switch_off"
之後在佈局文件中寫控件:
01.
<ToggleButton
02.
android:id=
"@+id/mTogBtn"
03.
android:layout_width=
"wrap_content"
04.
android:layout_height=
"wrap_content"
05.
android:layout_gravity=
"center_horizontal"
06.
android:background=
"@android:color/transparent"
07.
android:button=
"@drawable/toggle_btn"
08.
android:checked=
"false"
09.
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點擊監聽
01.
ToggleButton mTogBtn = (ToggleButton) findViewById(R.id.mTogBtn);
// 獲取到控件
02.
mTogBtn.setOnCheckedChangeListener(
new
OnCheckedChangeListener() {
03.
04.
@Override
05.
public
void
onCheckedChanged(CompoundButton buttonView,
boolean
isChecked) {
06.
// TODO Auto-generated method stub
07.
if
(isChecked){
08.
//選中
09.
}
else
{
10.
//未選中
11.
}
12.
}
13.
});
// 添加監聽事件
二.重寫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判斷是否有更改並做出相應的變化。
例如:
01.
@Override
02.
public
void
setEnabled(
boolean
enabled) {
03.
// TODO Auto-generated method stub
04.
mEnabled = enabled;
05.
mAlpha = enabled ? MAX_ALPHA : MAX_ALPHA/
2
;
06.
Log.d(
"enabled"
,enabled ?
"true"
:
"false"
);
07.
super
.setEnabled(enabled);
08.
invalidate();
09.
}
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.
}
還有就是要設置接口監聽狀態變化:
01.
/**
02.
* 設置 switch 狀態監聽
03.
* */
04.
public
void
setOnChangeListener(OnSwitchChangedListener listener) {
05.
switchListener = listener;
06.
}
07.
/**
08.
* switch 開關監聽接口
09.
* */
10.
public
interface
OnSwitchChangedListener{
11.
public
void
onSwitchChange(SlideSwitchView switchView,
boolean
isChecked);
12.
}
有的人可能會希望有SwitchButton在enabled設置爲false的時候,SwitchButton不能點擊且要改變顏色,使他看過去是不能點擊的。你可以進行如下操作(在學習別的人代碼中得到的提示,學以致用):
先初始化透明度:255爲不透明
1.
/** 最大透明度,就是不透明 */
2.
private
final
int
MAX_ALPHA =
255
;
3.
/** 當前透明度,這裏主要用於如果控件的enable屬性爲false時候設置半透明 ,即不可以點擊 */
4.
private
int
mAlpha = MAX_ALPHA;
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.
}
1.
android.graphics.Canvas.saveLayerAlpha(RectF bounds,
int
alpha,
int
saveFlags)
由於目前對於重寫VIEW的onDraw方法的瞭解不是很深入,所以這裏的DEMO中的幾個方法都是查看網絡之後加上自己的優化和註釋演變過來,等這一塊深入了後在重寫寫一篇關於這個的感受和使用說明。由於可能理解不是很深刻,如果有什麼不足之處可以提出,謝謝。
最後讓我們來看看效果如何,上圖: