自定义控件一般的几个步骤:
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. 搜索专题:HDU1241 Oil Deposits

    Oil Deposits Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Tot ...

  2. 如何将DataTable转换成List<T>

    using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.D ...

  3. newgrp - 登录到新的用户组中

    总览 (SYNOPSIS) newgrp [ group ] 描述 (DESCRIPTION) Newgrp 改变 调用者 的 用户组标识, 类似于 login(1). 调用者 仍旧 登录 在 系统 ...

  4. 关于Mysql select语句中拼接字符串的记录

    在mysql的SELECT语句中拼接两列(或多列)的字符串显示: mysql> select concat(dname,loc) from dept; 以上语句便把dept表的dname,loc ...

  5. PAT Basic 1041 考试座位号 (15 分)

    每个 PAT 考生在参加考试时都会被分配两个座位号,一个是试机座位,一个是考试座位.正常情况下,考生在入场时先得到试机座位号码,入座进入试机状态后,系统会显示该考生的考试座位号码,考试时考生需要换到考 ...

  6. PAT Basic 1046 划拳 (15 分)

    划拳是古老中国酒文化的一个有趣的组成部分.酒桌上两人划拳的方法为:每人口中喊出一个数字,同时用手比划出一个数字.如果谁比划出的数字正好等于两人喊出的数字之和,谁就赢了,输家罚一杯酒.两人同赢或两人同输 ...

  7. 02MySQL数据库

    1.MySQL启动和关闭 2.登录MySQL数据库 MySQL是一个需要账户名密码登录的数据库,登陆后使用,它提供了一个默认的root账号,使用安装时设置的密码即可登录. 格式1:cmd>  m ...

  8. Qt应用程序的发布

    1 Windows平台上的应用程序发布 Windows发布工具 windeployqt.exe是Qt自带的Windows平台发布工具.windeployqt.exe文件在Qt的bin目录下,Qt的每一 ...

  9. thinkphp5 yii2 laravel5.1 框架性能压测对比图

    nginx+php7环境,opcache已经开启,每测试一个框架都重启服务器并且预热访问三次,压测工具ab.exe. laravel,thinkphp,yii都已关闭debug,该做的优化命令都搞了, ...

  10. 在目标端重建sequence的脚本

    select 'create sequence '||SEQUENCE_OWNER||'.'||sequence_name|| ' minvalue '||min_value|| ' maxvalue ...