失眠网,内容丰富有趣,生活中的好帮手!
失眠网 > android 高仿ios开关 Android自定义view仿IOS开关效果

android 高仿ios开关 Android自定义view仿IOS开关效果

时间:2023-02-28 02:05:29

相关推荐

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:/3/20.

* Email:2911743255@

* 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开关效果》对你有帮助,请点赞、收藏,并留下你的观点哦!

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。