android 高仿ios开关,Android自定义view仿IOS开关效果
本文主要讲解如何在 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开关效果相关推荐
- android 清空canvas部分内容_Android自定义View实现圆形头像效果
在我们的APP中通常会遇到,展示圆形头像的需求,一般通过Glide就能实现,但是让我们做一个圆形头像,如果让我们自定义实现这种效果,该怎样做呢? 好,接下来本文通过三种方式来实现这种效果! 注意:这是 ...
- android记账本折线图_Android自定义View - 仿支付宝月账单折线图
前言 支付宝有个查看月账单的功能,最近一直在学习自定义View,于是就尝试着自己实现了一个类似的折线图. 下面是支付宝消费分析功能截图和自己实现的折线效果截图: 支付宝消费分析折线图.jpg 效果1. ...
- Android仿IOS滑动关机-自定义view系列(6)
Android仿IOS滑动关机-自定义view系列 功能简介 GIf演示 主要实现步骤-具体内容看github项目里的代码 Android技术生活交流 更多其他页面-自定义View-实用功能合集:点击 ...
- Android安卓仿IOS音量调节-自定义view系列(4)
Android安卓仿IOS音量调节-自定义view系列 功能简介 主要实现步骤 xml相关属性设置 java代码 Android技术生活交流 更多其他页面-自定义View-实用功能合集:点击查看 Gi ...
- android 高仿 探探卡片滑动,Android自定义View仿探探卡片滑动效果
Android自定义View仿探探卡片滑动这种效果网上有很多人已经讲解了实现思路,大多都用的是RecyclerView来实现的,但是我们今天来换一种实现思路,只用一个自定义的ViewGroup来搞定这 ...
- Android仿支付宝UI功能开发,Android 自定义view仿支付宝咻一咻功能
支付宝上有一个咻一咻的功能,就是点击图片后四周有水波纹的这种效果,今天也写一个类似的功能. 效果如下所示: 思路: 就是几个圆的半径不断在变大,这个可以使用动画缩放实现,还有透明动画 还有就是这是好几 ...
- android 仿360浮动,Android仿360悬浮小球自定义view实现示例
Android仿360悬浮小球自定义view实现示例 效果图如下: 实现当前这种类似的效果 和360小球 悬浮桌面差不错类似.这种效果是如何实现的呢.废话不多说 ,直接上代码. 1.新建工程,添加悬浮 ...
- android wear支付宝6,Android自定义View仿支付宝输入六位密码功能
跟选择银行卡界面类似,也是用一个PopupWindow,不过输入密码界面是一个自定义view,当输入六位密码完成后用回调在Activity中获取到输入的密码并以Toast显示密码.效果图如下: 自定义 ...
- android的动态tab,Android自定义view仿QQ的Tab按钮动画效果(示例代码)
话不多说 先上效果图 实现其实很简单,先用两张图 一张是背景的图,一张是笑脸的图片,笑脸的图片是白色,可能看不出来.实现思路:主要是再触摸view的时候同时移动这两个图片,但是移动的距离不一样,造成的 ...
- Android开发之制作圆形头像自定义View,直接引用工具类,加快开发速度。带有源代码学习
作者:程序员小冰,CSDN博客:http://blog.csdn.net/qq_21376985 QQ986945193 博客园主页:http://www.cnblogs.com/mcxiaobing ...
最新文章
- 使用Active Directory的常见问题2
- spark 1.5.2配置记录
- 洛谷 P2921 [USACO08DEC]在农场万圣节Trick or Treat on the Farm
- LeetCode 362. 敲击计数器(map)
- 获取php.ini配置信息,获得php所对应的配置文件(php.ini)信息
- QML笔记-自定义控件的2种点击方式(推荐第二种)
- 《Algorithms》Java 语言特性
- A Tour of the Dart Language(译文):五控制流语句
- 我和面试官的博弈:Redis 篇
- python 科研统计_Python科研统计作图Plotnine+Seaborn+matplotlib替代R ggplot2系列!(二)...
- 通过反编译深入理解Java String及intern
- 网页或PDF等复制文本的格式快速规范
- 20190404-亥姆霍兹方程、表面等离极化激元
- excel怎么录入身份证号码快速方便?
- JAVA实现汉字转换为拼音 自动识别常用多音字 JPinyin
- 数显之家快讯:【SHIO世硕心语】华为内部考核尺度爆光!
- python修改excel表格_python操作excel表格(xlrd/xlwt)以及表格的修改(OpenPyXL)
- 相似度论文系列-1:入门方法Towards a Unified Multi-Dimensional Evaluator for Text Generation
- 汽车CAN、LIN汇总
- Laravel 5.8+EasyWeChat 6.0开发公众号基本要求和文档
热门文章
- 【运维心得】server2012R2启动后任务栏卡死的终极解决
- 付宝支付功能思路总结
- 计算机网络实验搭建小型局域网,小型局域网组建实验报告..doc
- 怎么吧接受到数据传输大计算机,没有数据线怎么把手机文件传到电脑?告诉你三个小妙招,轻松解决...
- golang/Java实现求100以内的所有素(质)数和九九乘法表
- fifa足球世界服务器维护时间,FIFA足球世界什么时候出 游戏上线时间详解[多图]...
- 解决电脑连接了WiFi,却上不了网的问题
- JVM双亲委派机制执行流程图
- java 鱼眼照片的矫正_鱼眼镜头立体声校准OpenCV,Python
- 【容器技术】在裸机与虚拟机上运行容器:性能和优点