本文主要讲解如何在 Android 下实现高仿 iOS 的开关按钮,并非是在 Android 自带的 ToggleButton 上修改,而是使用 API 提供的 onDraw、onMeasure、Canvas 方法,纯手工绘制。基本原理就是在 Canvas 上叠着放两张图片,上面的图片根据手指触摸情况,不断移动,实现开关效果。

废话不说,上效果图,看看怎么样

样式如下:

网上也有实现这种效果的,但是大都滑动没中间消失的动画,或者是很复杂,今天用简单的绘图方式实现,重点就在onDraw里绘图。

功能点:

不滑出边界,超过一半自动切换(边界判断)

可滑动,也可点击(事件共存)

提供状态改变监听(设置回调)

通过属性设置初始状态、背景图片、滑动按钮(自定义属性)

自定义View的概述

Android 在绘制 View 时,其实就像蒙上眼睛在画板上画画,它并不知道应该把 View 画多大,画哪儿,怎么画。所以我们必须实现 View 的三个重要方法,以告诉它这些信息。即:onMeasure(画多大),onLayout(画哪儿),onDraw(怎么画)。

View的生命周期

在动手写之前,必须先了解以下几个概念:

1.View 的默认不支持 WRAP_CONTENT,必须重写 onMeasure 方法,通过 setMeasuredDimension() 设置尺寸

2.基本的事件分发机制:onClickListener 一定是在 onTouchEvent 之后执行

自定义View的流程

开始动手

1.导入开关的样式文件

@color/colorPrimary

@color/colorPrimaryDark

@color/colorAccent

2.开始自定义view,重点在onDraw()

/**

* Author:AND

* Time:2018/3/20.

* Email:2911743255@qq.com

* Description:

* Detail:仿IOS开关

*/

public class SwitchButton extends View {

//画笔

private final Paint mPaint = new Paint();

private static final double MBTNHEIGHT = 0.55;

private static final int OFFSET = 3;

private int mHeight;

private float mAnimate = 0L;

//此处命名不规范,目的和Android自带的switch有相同的用法

private boolean checked = false;

private float mScale;

private int mSelectColor;

private OnCheckedChangeListener mOnCheckedChangeListener;

public SwitchButton(Context context) {

this(context, null);

}

public SwitchButton(Context context, AttributeSet attrs) {

super(context, attrs);

TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.SwitchButton);

mSelectColor = typedArray.getColor(R.styleable.SwitchButton_buttonColor, Color.parseColor("#2eaa57"));

typedArray.recycle();

}

/**

* @param widthMeasureSpec

* @param heightMeasureSpec 高度是是宽度的0.55倍

*/

@Override

protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {

int width = MeasureSpec.getSize(widthMeasureSpec);

mHeight = (int) (MBTNHEIGHT * width);

setMeasuredDimension(width, mHeight);

}

@Override

protected void onDraw(Canvas canvas) {

super.onDraw(canvas);

mPaint.setStyle(Paint.Style.FILL);

mPaint.setAntiAlias(true);

mPaint.setColor(mSelectColor);

Rect rect = new Rect(0, 0, getWidth(), getHeight());

RectF rectf = new RectF(rect);

//绘制圆角矩形

canvas.drawRoundRect(rectf, mHeight / 2, mHeight / 2, mPaint);

//以下save和restore很重要,确保动画在中间一层 ,如果大家不明白,可以去搜下用法

canvas.save();

mPaint.setColor(Color.parseColor("#E6E6E6"));

mAnimate = mAnimate - 0.1f > 0 ? mAnimate - 0.1f : 0; // 动画标示 ,重绘10次,借鉴被人的动画

mScale = (!checked ? 1 - mAnimate : mAnimate);

canvas.scale(mScale, mScale, getWidth() - getHeight() / 2, rect.centerY());

//绘制缩放的灰色圆角矩形

canvas.drawRoundRect(rectf, mHeight / 2, mHeight / 2, mPaint);

mPaint.setColor(Color.WHITE);

Rect rect_inner = new Rect(OFFSET, OFFSET, getWidth() - OFFSET, getHeight() - OFFSET);

RectF rect_f_inner = new RectF(rect_inner);

//绘制缩放的白色圆角矩形,和上边的重叠实现灰色边框效果

canvas.drawRoundRect(rect_f_inner, (mHeight - 8) / 2, (mHeight - 8) / 2, mPaint);

canvas.restore();

//中间圆形平移

int sWidth = getWidth();

int bTranslateX = sWidth - getHeight();

final float translate = bTranslateX * (!checked ? mAnimate : 1 - mAnimate);

canvas.translate(translate, 0);

//以下两个圆带灰色边框

mPaint.setColor(Color.parseColor("#E6E6E6"));

canvas.drawCircle(getHeight() / 2, getHeight() / 2, getHeight() / 2 - OFFSET / 2, mPaint);

mPaint.setColor(Color.WHITE);

canvas.drawCircle(getHeight() / 2, getHeight() / 2, getHeight() / 2 - OFFSET, mPaint);

if (mScale > 0) {

mPaint.reset();

invalidate();

}

}

/**

* 事件分发

*

* @param event

* @return

*/

@Override

public boolean onTouchEvent(MotionEvent event) {

switch (event.getAction()) {

case MotionEvent.ACTION_DOWN:

return true;

case MotionEvent.ACTION_MOVE:

break;

case MotionEvent.ACTION_UP:

mAnimate = 1;

checked = !checked;

if (mOnCheckedChangeListener != null) {

mOnCheckedChangeListener.OnCheckedChanged(checked);

}

invalidate();

break;

}

return super.onTouchEvent(event);

}

/**

* 状态构造函数

*

* @return

*/

public boolean isChecked() {

return checked;

}

public void setChecked(boolean checked) {

this.checked = checked;

}

/**

* 构造函数

*

* @return

*/

public OnCheckedChangeListener getmOnCheckedChangeListener() {

return mOnCheckedChangeListener;

}

/**

* 调用方法

*

* @param mOnCheckedChangeListener

*/

public void setmOnCheckedChangeListener(OnCheckedChangeListener mOnCheckedChangeListener) {

this.mOnCheckedChangeListener = mOnCheckedChangeListener;

}

/**

* 滑动接口

*/

public interface OnCheckedChangeListener {

void OnCheckedChanged(boolean isChecked);

}

}

3.Activity中使用

@Override

protected void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(R.layout.activity_main);

mBtnSwitch = (SwitchButton) findViewById(R.id.switch_btn);

mBtnSwitch.setmOnCheckedChangeListener(new SwitchButton.OnCheckedChangeListener() {

@Override

public void OnCheckedChanged(boolean isChecked) {

Toast.makeText(MainActivity.this, "" + isChecked, Toast.LENGTH_SHORT).show();

}

});

}

当然,也可以上来就给开关定义状态值

mBtnSwitch.setChecked(boolean);

好了,自定义工作全部完成!!

那么300行左右的代码 完成了我们的仿iOS SwitchButton 的控件 SwitchView

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持脚本之家。

android 高仿ios开关,Android自定义view仿IOS开关效果相关推荐

  1. android 清空canvas部分内容_Android自定义View实现圆形头像效果

    在我们的APP中通常会遇到,展示圆形头像的需求,一般通过Glide就能实现,但是让我们做一个圆形头像,如果让我们自定义实现这种效果,该怎样做呢? 好,接下来本文通过三种方式来实现这种效果! 注意:这是 ...

  2. android记账本折线图_Android自定义View - 仿支付宝月账单折线图

    前言 支付宝有个查看月账单的功能,最近一直在学习自定义View,于是就尝试着自己实现了一个类似的折线图. 下面是支付宝消费分析功能截图和自己实现的折线效果截图: 支付宝消费分析折线图.jpg 效果1. ...

  3. Android仿IOS滑动关机-自定义view系列(6)

    Android仿IOS滑动关机-自定义view系列 功能简介 GIf演示 主要实现步骤-具体内容看github项目里的代码 Android技术生活交流 更多其他页面-自定义View-实用功能合集:点击 ...

  4. Android安卓仿IOS音量调节-自定义view系列(4)

    Android安卓仿IOS音量调节-自定义view系列 功能简介 主要实现步骤 xml相关属性设置 java代码 Android技术生活交流 更多其他页面-自定义View-实用功能合集:点击查看 Gi ...

  5. android 高仿 探探卡片滑动,Android自定义View仿探探卡片滑动效果

    Android自定义View仿探探卡片滑动这种效果网上有很多人已经讲解了实现思路,大多都用的是RecyclerView来实现的,但是我们今天来换一种实现思路,只用一个自定义的ViewGroup来搞定这 ...

  6. Android仿支付宝UI功能开发,Android 自定义view仿支付宝咻一咻功能

    支付宝上有一个咻一咻的功能,就是点击图片后四周有水波纹的这种效果,今天也写一个类似的功能. 效果如下所示: 思路: 就是几个圆的半径不断在变大,这个可以使用动画缩放实现,还有透明动画 还有就是这是好几 ...

  7. android 仿360浮动,Android仿360悬浮小球自定义view实现示例

    Android仿360悬浮小球自定义view实现示例 效果图如下: 实现当前这种类似的效果 和360小球 悬浮桌面差不错类似.这种效果是如何实现的呢.废话不多说 ,直接上代码. 1.新建工程,添加悬浮 ...

  8. android wear支付宝6,Android自定义View仿支付宝输入六位密码功能

    跟选择银行卡界面类似,也是用一个PopupWindow,不过输入密码界面是一个自定义view,当输入六位密码完成后用回调在Activity中获取到输入的密码并以Toast显示密码.效果图如下: 自定义 ...

  9. android的动态tab,Android自定义view仿QQ的Tab按钮动画效果(示例代码)

    话不多说 先上效果图 实现其实很简单,先用两张图 一张是背景的图,一张是笑脸的图片,笑脸的图片是白色,可能看不出来.实现思路:主要是再触摸view的时候同时移动这两个图片,但是移动的距离不一样,造成的 ...

  10. Android开发之制作圆形头像自定义View,直接引用工具类,加快开发速度。带有源代码学习

    作者:程序员小冰,CSDN博客:http://blog.csdn.net/qq_21376985 QQ986945193 博客园主页:http://www.cnblogs.com/mcxiaobing ...

最新文章

  1. 使用Active Directory的常见问题2
  2. spark 1.5.2配置记录
  3. 洛谷 P2921 [USACO08DEC]在农场万圣节Trick or Treat on the Farm
  4. LeetCode 362. 敲击计数器(map)
  5. 获取php.ini配置信息,获得php所对应的配置文件(php.ini)信息
  6. QML笔记-自定义控件的2种点击方式(推荐第二种)
  7. 《Algorithms》Java 语言特性
  8. A Tour of the Dart Language(译文):五控制流语句
  9. 我和面试官的博弈:Redis 篇
  10. python 科研统计_Python科研统计作图Plotnine+Seaborn+matplotlib替代R ggplot2系列!(二)...
  11. 通过反编译深入理解Java String及intern
  12. 网页或PDF等复制文本的格式快速规范
  13. 20190404-亥姆霍兹方程、表面等离极化激元
  14. excel怎么录入身份证号码快速方便?
  15. JAVA实现汉字转换为拼音 自动识别常用多音字 JPinyin
  16. 数显之家快讯:【SHIO世硕心语】华为内部考核尺度爆光!
  17. python修改excel表格_python操作excel表格(xlrd/xlwt)以及表格的修改(OpenPyXL)
  18. 相似度论文系列-1:入门方法Towards a Unified Multi-Dimensional Evaluator for Text Generation
  19. 汽车CAN、LIN汇总
  20. Laravel 5.8+EasyWeChat 6.0开发公众号基本要求和文档

热门文章

  1. 【运维心得】server2012R2启动后任务栏卡死的终极解决
  2. 付宝支付功能思路总结
  3. 计算机网络实验搭建小型局域网,小型局域网组建实验报告..doc
  4. 怎么吧接受到数据传输大计算机,没有数据线怎么把手机文件传到电脑?告诉你三个小妙招,轻松解决...
  5. golang/Java实现求100以内的所有素(质)数和九九乘法表
  6. fifa足球世界服务器维护时间,FIFA足球世界什么时候出 游戏上线时间详解[多图]...
  7. 解决电脑连接了WiFi,却上不了网的问题
  8. JVM双亲委派机制执行流程图
  9. java 鱼眼照片的矫正_鱼眼镜头立体声校准OpenCV,Python
  10. 【容器技术】在裸机与虚拟机上运行容器:性能和优点