-
刚开始接触开关样式的按钮是在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中的几个方法都是查看网络之后加上自己的优化和注释演变过来,等这一块深入了后在重写写一篇关于这个的感受和使用说明。由于可能理解不是很深刻,如果有什么不足之处可以提出,谢谢。
最后让我们来看看效果如何,上图: