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资源文件--作以下配置
<?xml version="1.0" encoding="utf-8"?>
<selector
xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_checked="true" android:drawable="@drawable/ios7_switch_on" />
<item android:drawable="@drawable/ios7_switch_off" />
</selector>
其中:android:state_checked="true" 表示选中on时候的,效果为:android:drawable="@drawable/ios7_switch_on"
反之就是未选中off情况下的效果:android:drawable="@drawable/ios7_switch_off"
之后在布局文件中写控件:
<ToggleButton
android:id="@+id/mTogBtn"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:background="@android:color/transparent"
android:button="@drawable/toggle_btn"
android:checked="false"
android:text=""
android:textOff=""
android:textOn="" />
这里的
android:textOn="" 表示:选中情况下显示的文本
android:textOff="" 表示:未选中情况下显示的文本
android:checked="false" 表示:初始化时候,默认是未选中的
android:button="@drawable/toggle_btn" 表示:button样式
android:background="@android:color/transparent" 表示:背景,这里不用它的默认背景,所以设置为透明
之后在主程序中实例化,并设置checked点击监听
ToggleButton mTogBtn = (ToggleButton) findViewById(R.id.mTogBtn); // 获取到控件
mTogBtn.setOnCheckedChangeListener(new OnCheckedChangeListener() {
@Override
public void onCheckedChanged(CompoundButton buttonView,boolean isChecked) {
// TODO Auto-generated method stub
if(isChecked){
//选中
}else{
//未选中
}
}
});// 添加监听事件
这样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判断是否有更改并做出相应的变化。
例如:
@Override
public void setEnabled(boolean enabled) {
// TODO Auto-generated method stub
mEnabled = enabled;
mAlpha = enabled ? MAX_ALPHA : MAX_ALPHA/2;
Log.d("enabled",enabled ? "true": "false");
super.setEnabled(enabled);
invalidate();
}
/** 自动判断切换至相反的属性 : true -->false ;false -->true */
public void toggle() {
setChecked(!mSwitchOn);
}
/** 设置选中的状态(选中:true 非选中: false) */
public void setChecked(boolean checked) {
mSwitchOn = checked;
invalidate();
}
还有,你如果是自定义的VIEW,你在里面设置了enabled属性,你必须在onTouchEvent(MotionEvent event)触摸操作的时候判断你所设置的enabled属性是否为true,是的话就可以相应点击事件,否则的话你要屏蔽掉点击事件。因为你自定义的view中的enabled属性并不知道他设定后会达到什么效果,这些都是要注意的点。
还有就是要设置接口监听状态变化:
/**
* 设置 switch 状态监听
* */
public void setOnChangeListener(OnSwitchChangedListener listener) {
switchListener = listener;
}
/**
* switch 开关监听接口
* */
public interface OnSwitchChangedListener{
public void onSwitchChange(SlideSwitchView switchView, boolean isChecked);
}
有的人可能会希望有SwitchButton在enabled设置为false的时候,SwitchButton不能点击且要改变颜色,使他看过去是不能点击的。你可以进行如下操作(在学习别的人代码中得到的提示,学以致用):
先初始化透明度:255为不透明
[java] view plaincopy
- /** 最大透明度,就是不透明 */
- private final int MAX_ALPHA = 255;
- /** 当前透明度,这里主要用于如果控件的enable属性为false时候设置半透明 ,即不可以点击 */
- private int mAlpha = MAX_ALPHA;
之后重写setEnabled方法,通过这个方法判断enabled属性值
@Override
public void setEnabled(boolean enabled) {
// TODO Auto-generated method stub
mEnabled = enabled;
mAlpha = enabled ? MAX_ALPHA : MAX_ALPHA/2;
super.setEnabled(enabled);
invalidate();
}
如果改变了enabled属性,系统便会查看UI是否需要变化,之后在UI方法onDraw(Canvas canvas)中调用:
android.graphics.Canvas.saveLayerAlpha(RectF bounds, int alpha, int saveFlags)
方法,其中的第2个属性alpha就是透明度,之后便可以实现相应的效果。
由于目前对于重写VIEW的onDraw方法的了解不是很深入,所以这里的DEMO中的几个方法都是查看网络之后加上自己的优化和注释演变过来,等这一块深入了后在重写写一篇关于这个的感受和使用说明。由于可能理解不是很深刻,如果有什么不足之处可以提出,谢谢。
最后让我们来看看效果如何,上图:
最后上源码DEMO:下载地址
- 我母亲遭遇勒索软件CryptoWall的全过程
- Android浏览器跨域数据窃取和Intent Scheme攻击
- 关于React Native项目在android上UI性能调试实践
- 一文读懂如何用 Python 实现6种排序算法
- 三星KNOX远程静默安装漏洞深入分析报告
- 技术分享:MSSQL注入xp_cmdshell
- 通过5个简单序列预测实例学习LSTM递归神经网络
- Google发现Windows 8.1 0day漏洞并公布漏洞验证程序(PoC)
- 携程React Native实践
- 数据分析告诉你:Php最不安全,Nginx比Apache安全
- 用python抓取摩拜单车API数据并做可视化分析(源码)
- 用Pandas在Python中可视化机器学习数据
- Intent 属性详解(下)
- 把复杂json解析成javabean思路:思路:
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- keras 回调函数Callbacks 断点ModelCheckpoint教程
- Mac下快速搭建PHP开发环境步骤详解
- PHP常用工具函数小结【移除XSS攻击、UTF8与GBK编码转换等】
- Ajax+PHP实现的模拟进度条功能示例
- python实例化对象的具体方法
- PHP5.6.8连接SQL Server 2008 R2数据库常用技巧分析总结
- YII框架关联查询操作示例
- Keras之fit_generator与train_on_batch用法
- django美化后台django-suit的安装配置操作
- python读取excel进行遍历/xlrd模块操作
- 浅谈Keras的Sequential与PyTorch的Sequential的区别
- python 制作python包,封装成可用模块教程
- 使用python脚本自动生成K8S-YAML的方法示例
- Python虚拟环境库virtualenvwrapper安装及使用
- tp5框架内使用tp3.2分页的方法分析