可滑动的ToggleButton(开关)
2013-12-28 17:25:01
网上看到一篇关于可滑动的ToogleButton的文章,有代码,觉得挺好,但是不符合我的要求,因此在他的代码基础上改了一些。(作者看到了勿喷啊,实在找不到原文了,只好把代码下载地址贴出来。)
源码下载地址: http://download.csdn.net/detail/zshq280017423/4240703
先来两张效果图:


然后上代码:
最主要的类是SlipButton.java
package com.util; import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnTouchListener; import com.view.SlipButton.R; public class SlipButton extends View implements OnTouchListener { private float DownX, NowX;// 按下时的x,当前的x
private float btn_on_left = ;
private float btn_off_left = ; private boolean NowChoose = false;// 记录当前按钮是否打开,true为打开,flase为关闭
private boolean isChecked;
private boolean OnSlip = false;// 记录用户是否在滑动的变量
private boolean isChgLsnOn = false; private OnChangedListener ChgLsn;
private Bitmap bg_on;
private Bitmap bg_off;
private Bitmap slip_btn; public SlipButton(Context context) {
super(context);
init();
} public SlipButton(Context context, AttributeSet attrs) {
super(context, attrs);
init();
} private void init() { // 初始化
bg_on = BitmapFactory.decodeResource(getResources(),
R.drawable.split_left_1);
bg_off = BitmapFactory.decodeResource(getResources(),
R.drawable.split_right_1);
slip_btn = BitmapFactory.decodeResource(getResources(),
R.drawable.split_1); btn_off_left = bg_off.getWidth() - slip_btn.getWidth(); setOnTouchListener(this); // 设置监听器,也可以直接复写OnTouchEvent
} @Override
protected void onDraw(Canvas canvas) {// 绘图函数
super.onDraw(canvas); Matrix matrix = new Matrix();
Paint paint = new Paint();
float x; if (NowX < (bg_on.getWidth() / )) { // 滑动到前半段与后半段的背景不同,在此做判断
x = NowX - slip_btn.getWidth() / ;
canvas.drawBitmap(bg_off, matrix, paint);// 画出关闭时的背景
} else {
x = bg_on.getWidth() - slip_btn.getWidth() / ;
canvas.drawBitmap(bg_on, matrix, paint);// 画出打开时的背景
} if (OnSlip) {// 是否是在滑动状态,
if (NowX >= bg_on.getWidth()) {// 是否划出指定范围,不能让游标跑到外头,必须做这个判断
x = bg_on.getWidth() - slip_btn.getWidth() / ;// 减去游标1/2的长度...
} else if (NowX < ) {
x = ;
} else {
x = NowX - slip_btn.getWidth() / ;
}
} else {// 非滑动状态
if (NowChoose) {// 根据现在的开关状态设置画游标的位置
x = btn_off_left;
canvas.drawBitmap(bg_on, matrix, paint);// 初始状态为true时应该画出打开状态图片
} else {
x = btn_on_left;
}
}
if (isChecked) {
canvas.drawBitmap(bg_on, matrix, paint);
x = btn_off_left;
isChecked = !isChecked;
} if (x < ) {// 对游标位置进行异常判断...
x = ;
} else if (x > bg_on.getWidth() - slip_btn.getWidth()) {
x = bg_on.getWidth() - slip_btn.getWidth();
}
canvas.drawBitmap(slip_btn, x, , paint);// 画出游标. } public boolean onTouch(View v, MotionEvent event) {
switch (event.getAction()) {// 根据动作来执行代码
case MotionEvent.ACTION_DOWN:// 按下
if (event.getX() > bg_on.getWidth()
|| event.getY() > bg_on.getHeight()) {
return false;
}
OnSlip = true;
DownX = event.getX();
NowX = DownX;
break; case MotionEvent.ACTION_MOVE:// 滑动
Log.d("David", "event.getX = " + event.getX());
Log.d("David", "event.getY = " + event.getY());
NowX = event.getX();
boolean LastChoose = NowChoose; if (NowX >= (bg_on.getWidth() / )) {
NowChoose = true;
} else {
NowChoose = false;
} if (isChgLsnOn && (LastChoose != NowChoose)) { // 如果设置了监听器,就调用其方法..
ChgLsn.OnChanged(NowChoose);
}
break; case MotionEvent.ACTION_UP:// 松开
OnSlip = false;
break;
default:
}
invalidate();// 重画控件
return true;
} public void SetOnChangedListener(OnChangedListener l) {// 设置监听器,当状态修改的时候
isChgLsnOn = true;
ChgLsn = l;
} public interface OnChangedListener {
abstract void OnChanged(boolean CheckState);
} public void setCheck(boolean isChecked) {
this.isChecked = isChecked;
NowChoose = isChecked;
} @Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { int measuredHeight = measureHeight(heightMeasureSpec);
int measuredWidth = measureWidth(widthMeasureSpec);
setMeasuredDimension(measuredWidth, measuredHeight);
} private int measureHeight(int measureSpec) { /*int specMode = MeasureSpec.getMode(measureSpec);
int specSize = MeasureSpec.getSize(measureSpec); // Default size if no limits are specified. int result = 500;
if (specMode == MeasureSpec.AT_MOST){
// Calculate the ideal size of your
// control within this maximum size.
// If your control fills the available
// space return the outer bound. result = specSize;
} else if (specMode == MeasureSpec.EXACTLY){
// If your control can fit within these bounds return that value.
result = specSize;
}*/
return bg_on.getHeight();
} private int measureWidth(int measureSpec) { /*int specMode = MeasureSpec.getMode(measureSpec);
int specSize = MeasureSpec.getSize(measureSpec); // Default size if no limits are specified.
int result = 500;
if (specMode == MeasureSpec.AT_MOST){
// Calculate the ideal size of your control
// within this maximum size.
// If your control fills the available space
// return the outer bound.
result = specSize;
} else if (specMode == MeasureSpec.EXACTLY){
// If your control can fit within these bounds return that value.
result = specSize;
}*/
return bg_on.getWidth();
}
}
代码比较简单,而且注释比较详细。
说一些几个问题:
1. onTouch()方法中得到的event.getX()和event.getY()是什么值?取值范围是多少?
刚开始我以为不管咱们的SlipButton放在什么位置,得到的event.getX()值因该是相对屏幕的坐标值,~~其实是错误的,event.getX()只有你的触摸点在当前SlipButton view的布局范围之内才会取到值的。但是值的范围可不仅仅是你的SlipButton view的大小哦,因为一旦你的触摸点在view范围之内触摸到,那么触摸点就可以移到View之外的任何地方了,所以取值范围应该是全屏哦,因此我们在代码里做了如下判断:
if (event.getX() > bg_on.getWidth()
|| event.getY() > bg_on.getHeight()) {
return false;
}
2. measureWidth()和measureHeight()为什么会返回一个固定值?
首先根据用途,我们自定义的SlipButton View根本没有必要去由调用者调整大小,因为这个ToggleButton本身就是起到开关作用的,在应用中应该是一致的,所以我让这两个方法返回固定值。关于onMeasure()方法根详细的描述,请看我的另一篇文章:http://www.cnblogs.com/wlrhnh/p/3479928.html
下载源码,请猛戳这里。
可滑动的ToggleButton(开关)的更多相关文章
- ToggleButton开关状态按钮控件
ToggleButton开关状态按钮控件 一.简介 1. 2.ToggleButton类结构 父类是CompoundButton,引包的时候注意下 二.ToggleButton开关状态按钮控件使用方法 ...
- OpenCV学习笔记——滑动条开关
由于opencv库中并没有专门为开关而设的函数,可以用滑动条做开关 代码: #include<highgui.h> #include<cv.h> int g_switch_va ...
- iOS:步进UIStepper、滑动块UISlider、开关UISwitch的基本使用
步进UIStepper.滑动块UISlider:当它们作为事件,被触发时,它们的值会发生改变.正因为如此,触发该事件时,可以一张一张翻阅浏览图片,,,, 步进UIStepper: @property( ...
- 绘制 ToggleButton --重写view
package com.example.compoundbuttonview.view; import com.example.compoundbuttonview.R; import android ...
- 自定义View-6 状态按钮 滑动 点击
View public class SwitchButton extends View implements OnClickListener, OnTouchListener { privat ...
- iOS7下滑动返回与ScrollView共存二三事
[转载请注明出处] = =不是整篇复制就算注明出处了亲... iOS7下滑动返回与ScrollView共存二三事 [前情回顾] 去年的时候,写了这篇帖子iOS7滑动返回.文中提到,对于多页面结构的应用 ...
- Ext 6.5.3 classic版本,自定义实现togglefield开关控件
1,在Ext 6.5.3的classic版中没有提供开关控件,参照modern版中 togglefield开关的实现,继承滑动器(sliderfield),自定义一个开关按钮.支持value绑定和点击 ...
- Android控件ToggleButton的使用方法
ToggleButton(开关button)是Android系统中比較简单的一个组件,是一个具有选中和未选择状态双状态的button.而且须要为不同的状态设置不同的显示文本. ToggleButton ...
- 转--2014年最新810多套android源码2.46GB免费一次性打包下载
转载自:http://www.eoeandroid.com/thread-497046-1-1.html 感谢该博客主人无私奉献~~ 下面的源码是从今年3月份开始不断整理源码区和其他网站上的安卓例子源 ...
随机推荐
- ORA-32004 参数设置过时的解决办法
启动时报错: 查看日志: view /opt/oracle11g/app/db/diag/rdbms/yldev/yldev/trace/alert_yldev.log 原来是plsql_debug ...
- 3 javascript
3 javascript javascript基础 html: 负责了一个页面的结构. css: 负责了一个页面的样式. javascript: 负责与用户进行交互. 1997年欧洲的计算机 ...
- hdu 4870 Rating
题目链接:hdu 4870 这题应该算是概率 dp 吧,刚开始看了好几个博客都一头雾水,总有些细节理不清楚,后来看了 hdu 4870 Rating (概率dp) 这篇博客终于有如醍醐灌顶,就好像是第 ...
- hdu 1575 Tr A(矩阵快速幂)
今天做的第二道矩阵快速幂题,因为是初次接触,各种奇葩错误整整调试了一下午.废话不说,入正题.该题应该属于矩阵快速幂的裸题了吧,知道快速幂原理(二进制迭代法,非递归版)后,剩下的只是处理矩阵乘法的功夫了 ...
- VirtualBox的网络配置,Host Only+NAT方式 (zhuan)
http://blog.csdn.net/xinghun_4/article/details/7969894 ***************************************** 其实网 ...
- contains
ArrayLIst类使用contains方法时要注意:放入ArrayList中的类必须要重写equals方法(既然equals重写了,那么 hash方法也应该重写,这两个方法一般同时重写):如果不重写 ...
- x265
1.编译库 https://bitbucket.org/multicoreware/x265/src/tip/build/README.txt?at=default 2.无法定位程序输入点x265_e ...
- XP系统电脑带安卓手机上网教程(无需adhoc补丁)
XP系统电脑带安卓手机上网教程(无需adhoc补丁) WIN7系统可以虚拟wifi热点,安卓手机连上这个热点就能上网.XP系统虚拟出来的wifi热点是adhoc形式的,原生的安卓系统并不支持adhoc ...
- 基于SourceTree 下的 Git Flow 模型
基于SourceTree 下的 Git Flow 模型 1. sourceTree 是一个开源的git 图形管理工具,可下载mac版本,windows版本 2. Git Flow 是一套使用Git进 ...
- Oracle session inactive状态临时表数据未清空问题
问题描述:Oracle数据库,java代码使用某数据库实例,获取connection并在使用结束关闭,而session未销毁,而是状态变为inactive从而导致临时表数据未清空. Oracle临时表 ...