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
網上類似的貼子很多,本文章實現的方試比較簡單,適合練手,畢竟自己寫出來的東西纔算是真正的到手的