Android自定义view仿IOS开关效果
GPT4.0+Midjourney绘画+国内大模型 会员永久免费使用!
【 如果你想靠AI翻身,你先需要一个靠谱的工具! 】
本文主要讲解如何在 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.导入开关的样式文件
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | < resources > <!-- Base application theme. --> < style name = "AppTheme" parent = "Theme.AppCompat.Light.DarkActionBar" > <!-- Customize your theme here. --> < item name = "colorPrimary" >@color/colorPrimary</ item > < item name = "colorPrimaryDark" >@color/colorPrimaryDark</ item > < item name = "colorAccent" >@color/colorAccent</ item > </ style > <!--高仿IOS7开关 - 样式--> < declare-styleable name = "SwitchButton" > < attr name = "buttonColor" format = "color" /> </ declare-styleable > </ resources > |
2.开始自定义view,重点在onDraw()
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 | /** * 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中使用
1 2 3 4 5 6 7 8 9 10 11 12 | @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(); } }); } |
当然,也可以上来就给开关定义状态值
好了,自定义工作全部完成!!
那么300行左右的代码 完成了我们的仿iOS SwitchButton 的控件 SwitchView
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持脚本之家。
微信公众号搜索 “ 脚本之家 ” ,选择关注
程序猿的那些事、送书等活动等着你
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若内容造成侵权/违法违规/事实不符,请将相关资料发送至 reterry123@163.com 进行投诉反馈,一经查实,立即处理!
相关文章
Android studio开发小型对话机器人app(实例代码)
这篇文章主要介绍了Android studio开发一个小型对话机器人app,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下2020-04-04详解Android控件之DatePicker、TimePicker探究
本篇文章主要介绍了Android控件之DatePicker、TimePicker探究,非常具有实用价值,需要的朋友可以参考下。2016-12-12Android之scrollview滑动使标题栏渐变背景色的实例代码
这篇文章主要介绍了Android之scrollview滑动使标题栏渐变背景色的实例代码,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧2018-05-05浅谈AnDroidDraw+DroidDraw实现Android程序UI设计的分析说明
本篇文章是对AnDroidDraw+DroidDraw实现Android程序UI设计进行了详细的分析介绍,需要的朋友参考下2013-05-05
最新评论