Android简单实现IOS按钮(动画效果)
###标题上写漏的还有一个自己加上的回弹效果
####花了点时间写了个稍稍简单点的,代码量也不是很多,比较容易理解
#####先来看看效果图
有回弹效果
无回弹效果
再来看一下这个尺寸的回弹效果
分析一下个人的思路
1.背景
我这里能想到的是先画一个左边的半圆,接着中间一个矩形,最后右边再来个半圆。(半圆可以使用画扇形的方式实现)
2.圆形按钮
这个不用多讲,就是使用canvas画圆
###接下来开始写代码
首先创建一个类IosSwitchBtnView继承View
public IosSwitchBtnView(Context context) {
this(context, null);
}
public IosSwitchBtnView(Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
initPaint();
}
public IosSwitchBtnView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
初始化画笔
private void initPaint() {
//背景
grayPain = new Paint();
grayPain.setColor(Color.GRAY);
grayPain.setAntiAlias(true); //抗锯齿
//开关
whitePaint = new Paint();
whitePaint.setColor(Color.WHITE);
whitePaint.setAntiAlias(true);
//切换后的背景颜色
greenPaint = new Paint();
greenPaint.setAntiAlias(true);
greenPaint.setColor(Color.parseColor("#FF4CD866")); //ios开关背景色
//初始化回弹效果距离
}
定义控件高度
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
int widthSize = MeasureSpec.getSize(widthMeasureSpec);
//高度等于宽度的60%
int heightSize = (int) (widthSize * 0.6f);
setMeasuredDimension(widthSize, heightSize);
//回弹效果的回弹距离
springBack = getHeight() / 3;
}
然后重写onDraw()方法,onDraw方法里面要做的事情不是很多
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
//根据状态选择当前画笔
Paint currentPaint = startPosition > getHeight() / 2 ? greenPaint : grayPain;
//左边扇形背景
RectF leftRectf = new RectF(0, 0, getHeight(), getHeight());
canvas.drawArc(leftRectf, 90, 180, true, currentPaint);
//中间矩形
canvas.drawRect(getHeight() / 2, 0, getWidth() - getHeight() / 2, getHeight(), currentPaint);
//右边扇形
RectF rightRectf = new RectF(getWidth() - getHeight(), 0, getWidth(), getHeight());
canvas.drawArc(rightRectf, 270, 180, true, currentPaint);
//白色圆形按钮
canvas.drawCircle(startPosition + getHeight() / 2, getHeight() / 2, getHeight() / 2 - borderWidth, whitePaint);
}
接下来是核心方法,接收控件的onTouchEvent事件,判断用户手指离开的位置,如果大于总宽度的一半,也就是打开开关操作,反之则为关闭
@Override
public boolean onTouchEvent(MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_UP:
// springBack = 0; //去除所有回弹效果
upPosition = event.getX();
if (!isChecked) {
openBtn();
} else {
closeBtn();
}
isChecked = !isChecked;
if (listener != null) {
listener.onCheckChangeListener(isChecked);
}
break;
case MotionEvent.ACTION_MOVE:
springBack = 0; //移动的时候去除回弹效果
float move = event.getX();
whichBtn(move - initMoveX);
//保存本次移动的位置
initMoveX = event.getX();
break;
case MotionEvent.ACTION_DOWN:
springBack = getHeight() / 3; //单点的时候开启回弹效果
initMoveX = event.getX();
break;
}
return true;
}
**注意:case MotionEvent.ACTION_UP: 里面的 springBack = 0; 是控制整个的回弹效果,如果不需要回弹效果可以设置等于0 //去除所有回弹效果。
使用handler延时展示动画
Handler handler = new Handler() {
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
case 1:
openBtn();
break;
case 2:
closeBtn();
break;
}
}
};
按钮开启的方法
private void openBtn() {
startPosition += getWidth() / 10;
//如果大于减去圆的直径
if (startPosition > getWidth() - getHeight() + springBack) {
startPosition = getWidth() - getHeight();
} else {
handler.sendEmptyMessageDelayed(1, 10);
}
}
按钮关闭
private void closeBtn() {
startPosition -= getWidth() / 10;
if (startPosition < -springBack) {
startPosition = 0;
} else {
handler.sendEmptyMessageDelayed(2, 10);
}
}
按钮状态改变监听接口
public interface IosOnCheckedChangListener {
void onCheckChangeListener(boolean isChecked);
}
public void setOnCheckedChangListener(IosOnCheckedChangListener listener) {
this.listener = listener;
}
布局文件的使用
<包名.IosSwitchBtnView
android:layout_width="300dp"
android:layout_height="wrap_content" />
**替换成自己的包名
代码结束
####最后结合图片总结一下实现思路:
从图片中可以看出其实原理就是通过控制中间圆形的起始位置来实现切换效果
-
开关的切换: 这里的开关切换可以通过判断手指最后离开的位置来获取当前是要开还是关,然后使用handler延时操作起始位置的变量+=10或者-=10来实现动画效果
-
**滑动效果:滑动效果需要重写onTouchEvent()方法,通过获取到里面的x轴的位置来进行滑动操作 **
滑动的距离 = (当前的滑动位置 - 最近一次的滑动位置 ) -
回弹效果:将最小与最大的位置分别加上或者减去回弹的变量,例如左边的回弹:只有当他等于最小位置减去回弹大小的时候才让他等于最小位置(这里的最小位置指的是圆形按钮的最小起始点),这样的话目标点将会是的负数,按钮也会相应的到达负数的位置,最后变回最小起始位置(0),效果完成
######END
网上类似的贴子很多,本文章实现的方试比较简单,适合练手,毕竟自己写出来的东西才算是真正的到手的