android 自定义切换按钮
来源:互联网 发布:tik江苏泰微课网络课程 编辑:程序博客网 时间:2024/05/17 08:50
import java.util.Timer;
import java.util.TimerTask;
import android.app.Activity;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Paint.FontMetrics;
import android.graphics.Shader;
import android.os.Handler;
import android.support.v4.util.TimeUtils;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnClickListener;
public class MyToggleBtn2 extends View implements OnClickListener{
/**
* 最小高度
*/
private float miniHeight;
/**
* 最小宽度
*/
private float miniWidth;
private Paint paint;
/**
* 选择开关左侧的文字信息
*/
private static final String showTextLeft = "直播";
/**
* 选择开关右侧的文字信息
*/
private static final String showTextRight = "分析师";
//默认显示右侧
private String showText ;
/**
* 在布局文件中声明该控件时,调用此方法
* @param context
* @param attrs
*/
public MyToggleBtn2(Context context, AttributeSet attrs) {
super(context, attrs);
init(context);
}
private Context ctx;
/**
* 初始化
*/
private void init(Context context) {
ctx = context;
showText = showTextRight;
paint = new Paint();
paint.setAntiAlias(true);// 抗矩齿
paint.setTextSize(sp2px(context,14));
FontMetrics fontMetrics = paint.getFontMetrics();
miniHeight = fontMetrics.bottom - fontMetrics.top+getPaddingTop()+getBottom()+sp2px(context,10);
float textWidth =0;
if(showTextLeft.length()>showTextRight.length()){
textWidth = paint.measureText(showTextLeft);
}else{
textWidth = paint.measureText(showTextRight);
}
paint.measureText(showTextLeft);
paint.measureText(showTextRight);
miniWidth = (float) (1.5*miniHeight+textWidth+getPaddingLeft()+getPaddingRight()+sp2px(context,10));
//滑动图片,左边界的最大值
slideLeftMax = (int) (miniWidth - miniHeight);
paint.setColor(Color.WHITE);
// 添加点击事件
setOnClickListener(this);
}
/**
* 设置为打开状态
*/
public void setOpenChecked(){
slideLeft = 0;
flushView();
}
/**
* 设置为关闭状态
*/
public void setCloseChecked(){
slideLeft = slideLeftMax;
flushView();
}
/**
* 当前的开关状态
* true 为开
* false 为关
*/
private boolean currState = false;
private int slideLeft = 0;
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
// 绘制背景图
//canvas.drawBitmap(bgBitmap, 0, 0, paint);
paint.setStrokeWidth(1);
paint.setStyle(paint.getStyle().FILL);
paint.setColor(Color.GRAY);
canvas.drawCircle((float)(miniHeight*0.5), (float)(miniHeight*0.5), (float)(miniHeight*0.5), paint);
canvas.drawRect((float)(miniHeight*0.5), 0, (float)(slideLeft+miniHeight*0.5), miniHeight, paint);
paint.setColor(Color.RED);
canvas.drawRect((float)((float)(slideLeft+miniHeight*0.5)), 0, (float)(miniWidth-miniHeight*0.5), miniHeight, paint);
canvas.drawCircle((float)(miniWidth-miniHeight*0.5+0.5), (float)(miniHeight*0.5), (float)(miniHeight*0.5), paint);
float textWidth = paint.measureText(showText);
FontMetrics fontMetrics = paint.getFontMetrics();
float fontTotalHeight = fontMetrics.bottom - fontMetrics.top;
float newY = getMeasuredHeight() / 2 - fontMetrics.descent+ (fontMetrics.descent - fontMetrics.ascent) / 2;
float baseX = 0;
paint.setColor(Color.WHITE);
if(!currState){
baseX = (float) ((getMeasuredWidth()-textWidth)-getPaddingRight()-miniHeight*0.5);
}else{
baseX = (float) (0+getPaddingLeft()+miniHeight*0.5);
}
//canvas.drawText(showText, baseX, newY, paint);
// 绘制滑动图片
//canvas.drawBitmap(slideBitmap, slideLeft, 0, paint);
paint.setColor(Color.WHITE);
canvas.drawCircle((float)(slideLeft+miniHeight*0.5+0.5), (float)(miniHeight*0.5), (float)(miniHeight*0.5+0.5), paint);
}
@Override
/**
* 指定view的大小
*/
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
// super.onMeasure(widthMeasureSpec, heightMeasureSpec);
// 当前view的宽度,就和背景图的大小一致
int measuredWidth = (int) miniWidth;
int measuredHeight = (int) miniHeight;
//指定测量的宽高
setMeasuredDimension(measuredWidth, measuredHeight);
}
Handler handler=new Handler();
Runnable runnable=new Runnable() {
@Override
public void run() {
// TODO Auto-generated method stub
//要做的事情
if(currState){
if(slideLeft<slideLeftMax){
isScroll = true;
slideLeft+=20;
handler.postDelayed(this, 100);
}else{
isScroll = false;
}
}else{
if(slideLeft>0){
isScroll = true;
slideLeft-=15;
handler.postDelayed(this, 100);
}else{
isScroll = false;
}
}
((Activity)(ctx)).runOnUiThread(new Runnable() {
@Override
public void run() {
// TODO Auto-generated method stub
if(currState){// 开状态
showText = showTextLeft;
if(onSwitchListener!=null){
onSwitchListener.OnRightClick();
}
}else{
showText = showTextRight;
if(onSwitchListener!=null){
onSwitchListener.OnLeftClick();
}
}
flushView();
}
});
}
};
/**
* 响应view的点击事件
*/
private boolean isScroll = false;
@Override
public void onClick(View v) {
// 如果发生了滑动的动作,就不执行以下代码
if(isSliding){
return ;
}
if(isScroll){
return;
}
currState = !currState;
//handler.postDelayed(runnable, 100);
// 切换按钮的开关状态
flushState();
}
/**
* 刷新状态
* 根据当前的状态,刷新页面
*/
private void flushState() {
if(currState){// 开状态
showText = showTextLeft;
slideLeft = slideLeftMax;
if(onSwitchListener!=null){
onSwitchListener.OnRightClick();
}
}else{
showText = showTextRight;
// 关状态
slideLeft = 0;
if(onSwitchListener!=null){
onSwitchListener.OnLeftClick();
}
}
flushView();
}
/**
* 上一个事件中的X坐标
*/
private int lastX;
/**
* down事件中的X坐标
*/
private int downX;
private int slideLeftMax;
/**
* 判断触摸时,是否发生滑动事件
*/
private boolean isSliding = false;
@Override
/**
* 重写该方法,处理触摸事件
* 如果该view消费了事件,那么,返回true
*/
public boolean onTouchEvent(MotionEvent event) {
// super 注释掉以后,onclick事件,就失效了,因为,点击这个动作,也是从onTouchEvent 方法中解析出来,符合一定的要求,就是一个点击事件
// 系统中,如果发现,view产生了up事件,就认为,发生了onclick动作,就行执行listener.onClick方法
super.onTouchEvent(event);
/*
* 点击切换开关,与触摸滑动切换开关,就会产生冲突
* 我们自己规定,如果手指在屏幕上移动,超过15个象素,就按滑动来切换开关,同时禁用点击切换开关的动作
*/
if(isScroll){
return true;
}
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
System.out.println("MotionEvent.ACTION_DOWN");
downX = lastX = (int) event.getX(); // 获得相对于当前view的坐标
// event.getRawX(); // 是相对于屏幕的坐标
// down 事件发生时,肯定不是滑动的动作
isSliding = false;
break;
case MotionEvent.ACTION_MOVE:
System.out.println("MotionEvent.ACTION_MOVE");
// 获得距离
int disX = (int) (event.getX() - lastX);
// 改变滑动图片的左边界
slideLeft+=disX;
flushView();
// 为lastX重新赋值
lastX = (int) event.getX();
// 判断是否发生滑动事件
if(Math.abs(event.getX()-downX)>15){ // 手指在屏幕上滑动的距离大于15象素
isSliding = true;
}
break;
case MotionEvent.ACTION_UP:
System.out.println("MotionEvent.ACTION_UP");
// 只有发生了滑动,才执行以下代码
if (isSliding) {
// 如果slideLeft > 最大值的一半 当前是开状态
// 否则就是关的状态
if (slideLeft > slideLeftMax / 2) { // 开状态
currState = true;
} else {
currState = false;
}
flushState();
}
break;
}
return true;
}
/**
* 刷新页面
*/
private void flushView() {
// 保证 slideLeft >=0 同时 <= slideLeftMax
if(slideLeft<0){
slideLeft = 0;
}
if(slideLeft>slideLeftMax){
slideLeft = slideLeftMax;
}
invalidate();// 刷新页面
}
public float sp2px(Context ctx,float sp){
return (float) (ctx.getResources().getDisplayMetrics().density*sp+0.5);
}
private IOnSwitchListener onSwitchListener;
public interface IOnSwitchListener{
public void OnLeftClick();
public void OnRightClick();
}
public void setOnSwitchListener(IOnSwitchListener onSwitchListener){
this.onSwitchListener = onSwitchListener;
}
import java.util.TimerTask;
import android.app.Activity;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Paint.FontMetrics;
import android.graphics.Shader;
import android.os.Handler;
import android.support.v4.util.TimeUtils;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnClickListener;
public class MyToggleBtn2 extends View implements OnClickListener{
/**
* 最小高度
*/
private float miniHeight;
/**
* 最小宽度
*/
private float miniWidth;
private Paint paint;
/**
* 选择开关左侧的文字信息
*/
private static final String showTextLeft = "直播";
/**
* 选择开关右侧的文字信息
*/
private static final String showTextRight = "分析师";
//默认显示右侧
private String showText ;
/**
* 在布局文件中声明该控件时,调用此方法
* @param context
* @param attrs
*/
public MyToggleBtn2(Context context, AttributeSet attrs) {
super(context, attrs);
init(context);
}
private Context ctx;
/**
* 初始化
*/
private void init(Context context) {
ctx = context;
showText = showTextRight;
paint = new Paint();
paint.setAntiAlias(true);// 抗矩齿
paint.setTextSize(sp2px(context,14));
FontMetrics fontMetrics = paint.getFontMetrics();
miniHeight = fontMetrics.bottom - fontMetrics.top+getPaddingTop()+getBottom()+sp2px(context,10);
float textWidth =0;
if(showTextLeft.length()>showTextRight.length()){
textWidth = paint.measureText(showTextLeft);
}else{
textWidth = paint.measureText(showTextRight);
}
paint.measureText(showTextLeft);
paint.measureText(showTextRight);
miniWidth = (float) (1.5*miniHeight+textWidth+getPaddingLeft()+getPaddingRight()+sp2px(context,10));
//滑动图片,左边界的最大值
slideLeftMax = (int) (miniWidth - miniHeight);
paint.setColor(Color.WHITE);
// 添加点击事件
setOnClickListener(this);
}
/**
* 设置为打开状态
*/
public void setOpenChecked(){
slideLeft = 0;
flushView();
}
/**
* 设置为关闭状态
*/
public void setCloseChecked(){
slideLeft = slideLeftMax;
flushView();
}
/**
* 当前的开关状态
* true 为开
* false 为关
*/
private boolean currState = false;
private int slideLeft = 0;
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
// 绘制背景图
//canvas.drawBitmap(bgBitmap, 0, 0, paint);
paint.setStrokeWidth(1);
paint.setStyle(paint.getStyle().FILL);
paint.setColor(Color.GRAY);
canvas.drawCircle((float)(miniHeight*0.5), (float)(miniHeight*0.5), (float)(miniHeight*0.5), paint);
canvas.drawRect((float)(miniHeight*0.5), 0, (float)(slideLeft+miniHeight*0.5), miniHeight, paint);
paint.setColor(Color.RED);
canvas.drawRect((float)((float)(slideLeft+miniHeight*0.5)), 0, (float)(miniWidth-miniHeight*0.5), miniHeight, paint);
canvas.drawCircle((float)(miniWidth-miniHeight*0.5+0.5), (float)(miniHeight*0.5), (float)(miniHeight*0.5), paint);
float textWidth = paint.measureText(showText);
FontMetrics fontMetrics = paint.getFontMetrics();
float fontTotalHeight = fontMetrics.bottom - fontMetrics.top;
float newY = getMeasuredHeight() / 2 - fontMetrics.descent+ (fontMetrics.descent - fontMetrics.ascent) / 2;
float baseX = 0;
paint.setColor(Color.WHITE);
if(!currState){
baseX = (float) ((getMeasuredWidth()-textWidth)-getPaddingRight()-miniHeight*0.5);
}else{
baseX = (float) (0+getPaddingLeft()+miniHeight*0.5);
}
//canvas.drawText(showText, baseX, newY, paint);
// 绘制滑动图片
//canvas.drawBitmap(slideBitmap, slideLeft, 0, paint);
paint.setColor(Color.WHITE);
canvas.drawCircle((float)(slideLeft+miniHeight*0.5+0.5), (float)(miniHeight*0.5), (float)(miniHeight*0.5+0.5), paint);
}
@Override
/**
* 指定view的大小
*/
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
// super.onMeasure(widthMeasureSpec, heightMeasureSpec);
// 当前view的宽度,就和背景图的大小一致
int measuredWidth = (int) miniWidth;
int measuredHeight = (int) miniHeight;
//指定测量的宽高
setMeasuredDimension(measuredWidth, measuredHeight);
}
Handler handler=new Handler();
Runnable runnable=new Runnable() {
@Override
public void run() {
// TODO Auto-generated method stub
//要做的事情
if(currState){
if(slideLeft<slideLeftMax){
isScroll = true;
slideLeft+=20;
handler.postDelayed(this, 100);
}else{
isScroll = false;
}
}else{
if(slideLeft>0){
isScroll = true;
slideLeft-=15;
handler.postDelayed(this, 100);
}else{
isScroll = false;
}
}
((Activity)(ctx)).runOnUiThread(new Runnable() {
@Override
public void run() {
// TODO Auto-generated method stub
if(currState){// 开状态
showText = showTextLeft;
if(onSwitchListener!=null){
onSwitchListener.OnRightClick();
}
}else{
showText = showTextRight;
if(onSwitchListener!=null){
onSwitchListener.OnLeftClick();
}
}
flushView();
}
});
}
};
/**
* 响应view的点击事件
*/
private boolean isScroll = false;
@Override
public void onClick(View v) {
// 如果发生了滑动的动作,就不执行以下代码
if(isSliding){
return ;
}
if(isScroll){
return;
}
currState = !currState;
//handler.postDelayed(runnable, 100);
// 切换按钮的开关状态
flushState();
}
/**
* 刷新状态
* 根据当前的状态,刷新页面
*/
private void flushState() {
if(currState){// 开状态
showText = showTextLeft;
slideLeft = slideLeftMax;
if(onSwitchListener!=null){
onSwitchListener.OnRightClick();
}
}else{
showText = showTextRight;
// 关状态
slideLeft = 0;
if(onSwitchListener!=null){
onSwitchListener.OnLeftClick();
}
}
flushView();
}
/**
* 上一个事件中的X坐标
*/
private int lastX;
/**
* down事件中的X坐标
*/
private int downX;
private int slideLeftMax;
/**
* 判断触摸时,是否发生滑动事件
*/
private boolean isSliding = false;
@Override
/**
* 重写该方法,处理触摸事件
* 如果该view消费了事件,那么,返回true
*/
public boolean onTouchEvent(MotionEvent event) {
// super 注释掉以后,onclick事件,就失效了,因为,点击这个动作,也是从onTouchEvent 方法中解析出来,符合一定的要求,就是一个点击事件
// 系统中,如果发现,view产生了up事件,就认为,发生了onclick动作,就行执行listener.onClick方法
super.onTouchEvent(event);
/*
* 点击切换开关,与触摸滑动切换开关,就会产生冲突
* 我们自己规定,如果手指在屏幕上移动,超过15个象素,就按滑动来切换开关,同时禁用点击切换开关的动作
*/
if(isScroll){
return true;
}
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
System.out.println("MotionEvent.ACTION_DOWN");
downX = lastX = (int) event.getX(); // 获得相对于当前view的坐标
// event.getRawX(); // 是相对于屏幕的坐标
// down 事件发生时,肯定不是滑动的动作
isSliding = false;
break;
case MotionEvent.ACTION_MOVE:
System.out.println("MotionEvent.ACTION_MOVE");
// 获得距离
int disX = (int) (event.getX() - lastX);
// 改变滑动图片的左边界
slideLeft+=disX;
flushView();
// 为lastX重新赋值
lastX = (int) event.getX();
// 判断是否发生滑动事件
if(Math.abs(event.getX()-downX)>15){ // 手指在屏幕上滑动的距离大于15象素
isSliding = true;
}
break;
case MotionEvent.ACTION_UP:
System.out.println("MotionEvent.ACTION_UP");
// 只有发生了滑动,才执行以下代码
if (isSliding) {
// 如果slideLeft > 最大值的一半 当前是开状态
// 否则就是关的状态
if (slideLeft > slideLeftMax / 2) { // 开状态
currState = true;
} else {
currState = false;
}
flushState();
}
break;
}
return true;
}
/**
* 刷新页面
*/
private void flushView() {
// 保证 slideLeft >=0 同时 <= slideLeftMax
if(slideLeft<0){
slideLeft = 0;
}
if(slideLeft>slideLeftMax){
slideLeft = slideLeftMax;
}
invalidate();// 刷新页面
}
public float sp2px(Context ctx,float sp){
return (float) (ctx.getResources().getDisplayMetrics().density*sp+0.5);
}
private IOnSwitchListener onSwitchListener;
public interface IOnSwitchListener{
public void OnLeftClick();
public void OnRightClick();
}
public void setOnSwitchListener(IOnSwitchListener onSwitchListener){
this.onSwitchListener = onSwitchListener;
}
}
0 0
- android 自定义切换按钮
- UI--Android中的状态切换按钮自定义
- UI--Android中的状态切换按钮自定义
- Android自定义组合控件--底部多按钮切换
- 自定义PowerPoint切换幻灯片按钮
- Android自定义控件2:自定义带下划线的文本或按钮、组合使用可切换tab
- Android ImageSwitcher 图片切换 按钮点击切换
- Android切换按钮 带文字
- Android按钮状态的切换
- XML自定义按钮样子-点击切换图片
- 自定义按钮实现标签栏切换
- swiper插件自定义切换箭头按钮
- 自定义控件1_切换按钮
- android 自定义返回按钮
- 编写Android自定义按钮
- Android自定义按钮样式
- Android自定义返回按钮
- Android自定义按钮
- Android 之打造仿微信页面切换公共方法及实现
- 【设计谈】字体与排版
- win7系统下装ubantu
- 【matlab】:matlab实现求图像中的多个质心
- Makefile的编写
- android 自定义切换按钮
- 【From牛客网】各厂笔试训练题目
- function taoBaoJiaGe($url)
- Sublime Text中使用Autoprefixer功能
- 第1周 C语言及程序设计初步 例程1- if语句的嵌套
- CentOS7 扩容 / 目录
- android studio AIDL 编译时 错误:找不到符号
- python group()
- Android学习:简单自定义View