自定义控件一般的几个步骤:
1.初始化相关背景图片,布局文件,自定义属性
2.设置控件宽高OnMeasure()
3.布局或者排版OnLayout()
4.绘制控件OnDraw()
5.处理触摸事件OnTouchEvent()
 public class SwitchView extends View implements View.OnTouchListener {

     //开关状态图片
private Bitmap mSwitch_on, mSwitch_off, mSwitch_circle; //开关状态 默认关闭
private boolean mCurrentState = false; //开关切换回调接口
private OnSwitchChangedListener mOnSwitchChangedListener; //X轴按下坐标
private int downX;
//X轴移动时触点坐标
private int moveX;
//X轴偏移量
private int left = 0;
//最大可移动距离
private int max; public SwitchView(Context context) {
super(context);
init();
} public SwitchView(Context context, AttributeSet attrs) {
super(context, attrs);
init();
} public SwitchView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
init();
} //1 初始化图片(加载)
private void init() {
Resources resr = getResources();
mSwitch_on = BitmapFactory.decodeResource(resr, R.mipmap.switch_on);
mSwitch_off = BitmapFactory.decodeResource(resr, R.mipmap.switch_off);
mSwitch_circle = BitmapFactory.decodeResource(resr, R.mipmap.switch_circle);
setOnTouchListener(this);
} //2 设置控件宽高(测量)
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int widthSize = mSwitch_off.getWidth();
int heightSize = mSwitch_off.getHeight();
max = mSwitch_off.getWidth() - mSwitch_circle.getWidth();
setMeasuredDimension(widthSize, heightSize);
} //3 布局(排版)
@Override
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
super.onLayout(changed, left, top, right, bottom);
} //4 最后绘制控件
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
Matrix m = new Matrix();
Paint p = new Paint();
if (mCurrentState) {
canvas.drawBitmap(mSwitch_on, m, p);
} else {
canvas.drawBitmap(mSwitch_off, m, p);
}
canvas.drawBitmap(mSwitch_circle, left, 0, p);
} //5 触摸事件
@Override
public boolean onTouch(View v, MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
downX = (int) event.getX();//初始X轴按下坐标
break;
case MotionEvent.ACTION_MOVE:
moveX = (int) event.getX();
left = moveX - downX;
if (!mCurrentState) {
//关闭状态边界处理
if (left < 0) {
left = 0;
} else if (left > max) {
left = max;
}
} else {
//开启状态边界处理
left = moveX - downX;
if (left > 0) {//向右滑
left = max;
} else if (Math.abs(left) > max) {
left = 0;
} else {
left = max - Math.abs(left);
}
}
break;
case MotionEvent.ACTION_UP:
case MotionEvent.ACTION_CANCEL://抬起时的判断
int upX = (int) event.getX();
boolean state = false; //滑动是否成功
//1 关闭状态
if (!mCurrentState) {
//滑动是否成功
//a 移动距离超过 1/2 的滑动宽度
//b 触摸点在滑动区域,开启按钮
state = (moveX - downX) >= max / 2 || upX >= max;
if (state) {
left = max;
mCurrentState = true;
} else {
left = 0;
}
} else {
//2 开启状态,判断滑动是否成功
//a 移动距离超过 1/2 的滑动宽度
//b 触摸点在滑动区域,关闭按钮
state = (downX - moveX) >= max / 2 || upX <= max;
if (state) {
left = 0;
mCurrentState = false;
} else {
left = max;
}
}
//滑动成功 且 回调接口不能空 触发回调方法
if (state && null != mOnSwitchChangedListener) {
mOnSwitchChangedListener.onSwitchChanged(mCurrentState);
}
break;
}
invalidate();
return true;
} //开关切换回调接口
public interface OnSwitchChangedListener {
void onSwitchChanged(boolean isOpen);
} public void setOnSwitchChangedListener(OnSwitchChangedListener listener) {
this.mOnSwitchChangedListener = listener;
} public void setCurrentState(boolean isOpen) {
mCurrentState = isOpen;
left = isOpen ? max : 0;
invalidate();
} }

自定义控件 - 切换开关:SwitchView的更多相关文章

  1. Qt之自定义控件(开关按钮)

    简述 接触过IOS系统的童鞋们应该对开关按钮很熟悉,在设置里面经常遇到,切换时候的滑动效果比较帅气. 通常说的开关按钮,有两个状态:on.off. 下面,我们利用自定义控件来实现一个开关按钮. 简述 ...

  2. android自定义控件——以滑动开关为例

    0.引言 (1)Android从4.0开始提供了switch的滑动开关效果组件,但是之前版本却没有 (2)很多时候我们写程序,都希望把有用的通用的通用的东西封装起来,以便以后重用. 本文根据组件开发思 ...

  3. android自定义控件一站式入门

    自定义控件 Android系统提供了一系列UI相关的类来帮助我们构造app的界面,以及完成交互的处理. 一般的,所有可以在窗口中被展示的UI对象类型,最终都是继承自View的类,这包括展示最终内容的非 ...

  4. ASP.NET MVC学习之母版页和自定义控件的使用

    一.母板页_Layout.cshtml类似于传统WebForm中的.master文件,起到页面整体框架重用的目地1.母板页代码预览 <!DOCTYPE html> <html> ...

  5. C# 自定义控件VS用户控件

    1 自定义控件与用户控件区别 WinForm中, 用户控件(User Control):继承自 UserControl,主要用于开发 Container 控件,Container控件可以添加其他Con ...

  6. 自定义控件之 圆形 / 圆角 ImageView

    一.问题在哪里? 问题来源于app开发中一个很常见的场景——用户头像要展示成圆的:       二.怎么搞? 机智的我,第一想法就是,切一张中间圆形透明.四周与底色相同.尺寸与头像相同的蒙板图片,盖在 ...

  7. 如何开发FineReport的自定义控件?

    FineReport作为插件化开发的报表软件,有些特殊需求的功能需要自己开发,开发的插件包帆软官方有提提供,可以去帆软论坛上找,本文将主要介绍如何开发一个自定义控件,这里讲讲方法论. 第一步:实例化一 ...

  8. WPF自定义控件第二 - 转盘按钮控件

    继之前那个控件,又做了一个原理差不多的控件.这个控件主要模仿百度贴吧WP版帖子浏览界面左下角那个弹出的按钮盘.希望对大家有帮助. 这个控件和之前的也差不多,为了不让大家白看,文章最后发干货. 由于这个 ...

  9. 【Win 10应用开发】AdaptiveTrigger在自定义控件中是可以触发的

    前些天,看到有网友给我留言,说AdaptiveTrigger在自定义控件(模板化控件)中不能触发.因为当时我正在写其他的代码,就没有去做实验来验证,于是我就给这位网友提了使用GotoVisualSta ...

随机推荐

  1. HNUSTOJ-1690 千纸鹤

    1690: 千纸鹤 时间限制: 1 Sec  内存限制: 128 MB提交: 992  解决: 296[提交][状态][讨论版] 题目描述  圣诞节快到了,校园里到处弥漫着粉红色的气息.又是一个情侣秀 ...

  2. Django、Flask、Tornado的区别?

    Django:Python 界最全能的 web 开发框架,battery-include 各种功能完备,可维护性和开发速度一级棒.常有人说 Django 慢,其实主要慢在 Django ORM 与数据 ...

  3. UIDynamic物理引擎

    iOS开发拓展篇—UIDynamic(简单介绍) 一.简单介绍 1.什么是UIDynamic UIDynamic是从iOS 7开始引入的一种新技术,隶属于UIKit框架 可以认为是一种物理引擎,能模拟 ...

  4. 2018-8-10-dotnet-core-编程规范

    title author date CreateTime categories dotnet core 编程规范 lindexi 2018-08-10 19:16:52 +0800 2018-05-0 ...

  5. thrift的php-v0.12版本类自动加载失败

    参考网上教程,使用$loader->registerDefinition('Sample', $GEN_DIR); 但是会报PHP Fatal error:  Uncaught Error: C ...

  6. Zabbix--03 邮件报警、微信报警

    目录 一. 邮件报警 1.定义发件人 2.定义收件人 3.优化告警信息 二. 微信报警 1.查看配置文件里的脚本目录路径 2.将weixin.py放在zabbix特定目录 3.配置发信人 4.配置收信 ...

  7. python 写matlab中的加性高斯白噪声AWGN

    定义 原始信号:x 噪声信号:n 信噪比:SNR 信号长度:N def wgn(x, snr): snr = 10**(snr/10.0) xpower = np.sum(x**2)/len(x) n ...

  8. Codeforces 962 /2错误 相间位置排列 堆模拟 X轴距离最小值 前向星点双连通分量求只存在在一个简单环中的边

    A #include <bits/stdc++.h> #define PI acos(-1.0) #define mem(a,b) memset((a),b,sizeof(a)) #def ...

  9. SVN服务之VisualSVN-Server和TortoiseSVN

    SVN客户端程序:TortoiseSVN SVN服务器程序:VisualSVN-Server   目前有个项目,需要版本服务器,由于习惯了svn的使用,让这边搭建一台svn服务器,做了一下整理,只满足 ...

  10. 阅读《Effective Java》每条tips的理解和总结(1)

    <Effective Java>这本书的结构是90来条tips,有长有短,每条tip都值的学习.这里根据对书中每条tip的理解做简短的总结,方便日后回顾.持续更新~ 1. 考虑用静态方法代 ...