项目重用到了IOS风格的一个开关SwitchButton,网上也找了蛮多,但是文件都比较大,所以自己写了一个。
先看效果图
github:https://github.com/xiebinJava/SwitchButton
下面直接上代码:
package com.xie.brad.myswitchbutton.MyButton;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.RectF;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
import com.xie.brad.myswitchbutton.R;
import java.util.Date;
/**
* Created by dell on 2017/10/20.
*/
public class SwitchButton extends View {
private Paint paint;
private float downX;
private float moveX;
private float BTmoveX;
private float dx;
private float maxX;
private boolean isOpen;
private Date date;
private long downTime;
private long upTime;
private int mWidth;
private int mHeight;
private int sRight;
private float sBottom;
private float sLeft;
private int sTop;
private float sWidth;
private float sHeight;
private float sCenterX;
private float sCenterY;
private Path sPath = new Path();
private int bLeft;
private int bTop;
private float bBottom;
private float bRight;
private float bWidth;
private float bRadius;
private float bStrokWidth;
private float sScale;
private float sScaleCenterX;
private OnSwitchListener switchListener;
private boolean firstState;
public SwitchButton(Context context) {
super(context, null);
}
public SwitchButton(Context context, AttributeSet attrs) {
super(context, attrs, 0);
paint = new Paint();
date = new Date();
TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.SwitchButton);
firstState = typedArray.getBoolean(R.styleable.SwitchButton_switch_state, false);
isOpen = firstState;
}
public SwitchButton(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
// height = width * 0.65 左右
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
int widthSize = MeasureSpec.getSize(widthMeasureSpec);
int heightSize = (int) (widthSize * 0.65f);
setMeasuredDimension(widthSize, heightSize);
}
@Override
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
super.onLayout(changed, left, top, right, bottom);
}
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
mWidth = w; // 视图自身宽度
mHeight = h; // 视图自身高度
sLeft = sTop = 0; // 田径场 左和上的坐标
sRight = mWidth; // 田径场 右占自身的全部
sBottom = mHeight * 0.8f; // 田径场底部 占全身的百分之八十, 下面预留百分之二十的空间画按钮阴影。
sWidth = sRight - sLeft; // 田径场的宽度
sHeight = sBottom - sTop; // 田径场的高度
sCenterX = (sRight + sLeft) / 2; // 田径场的X轴中心坐标
sCenterY = (sBottom + sTop) / 2; // 田径场的Y轴中心坐标
RectF sRectF = new RectF(sLeft, sTop, sBottom, sBottom);
sPath.arcTo(sRectF, 90, 180);
sRectF.left = sRight - sBottom;
sRectF.right = sRight;
sPath.arcTo(sRectF, 270, 180);
sPath.close(); // path准备田径场的路径
bLeft = bTop = 0;
bRight = bBottom = sBottom; // 和田径场同高,同宽的节奏, 没错包裹圆形的肯定是个正方形是小孩子都知道的。
bWidth = bRight - bLeft;
final float halfHeightOfS = (sBottom - sTop) / 2;
bRadius = halfHeightOfS * 0.9f; // 按钮的半径
bStrokWidth = 2 * (halfHeightOfS - bRadius); // 按钮的边框
sScale = 1 - bStrokWidth / sHeight; //替换之前的0.98<
sScaleCenterX = sWidth - halfHeightOfS;
if (isOpen){
BTmoveX = sWidth - bWidth / 2;
}else {
BTmoveX = bWidth / 2;
}
maxX = sWidth - bWidth;
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
paint.setAntiAlias(true);
paint.setStyle(Paint.Style.FILL);
if (isOpen) {
paint.setColor(getResources().getColor(R.color.colorPrimary));
} else {
paint.setColor(0xffcccccc);
}
canvas.drawPath(sPath, paint); // 画出田径场
canvas.save();
paint.setAntiAlias(true);
paint.setStyle(Paint.Style.FILL);
paint.setColor(getResources().getColor(R.color.colorAccent));
canvas.drawCircle(BTmoveX, bWidth / 2, bRadius, paint); // 按钮白底
canvas.restore();
paint.reset();
}
@Override
public boolean onTouchEvent(MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
downX = event.getX();
downTime = date.getTime();
firstState = isOpen;
break;
case MotionEvent.ACTION_MOVE:
moveX = event.getX();
dx = moveX - downX;
if (!isOpen) {
if (dx < 0) {
BTmoveX = bWidth / 2;
isOpen = false;
} else if (dx > maxX) {
BTmoveX = maxX + (bWidth / 2);
isOpen = true;
} else {
BTmoveX = dx + (bWidth / 2);
}
} else {
if (dx > 0) {
BTmoveX = maxX + bWidth / 2;
isOpen = true;
} else if (Math.abs(dx) > maxX) {
BTmoveX = bWidth / 2;
isOpen = false;
} else {
BTmoveX = maxX - Math.abs(dx) + (bWidth / 2);
}
}
invalidate();
break;
case MotionEvent.ACTION_UP:
upTime = date.getTime();
if (Math.abs(dx) < 3 && upTime - downTime < 1000) {
if (isOpen) {
isOpen = false;
BTmoveX = bWidth / 2;
firstState = false;
switchListener.closebutton();
} else {
isOpen = true;
BTmoveX = maxX + bWidth / 2;
firstState = true;
switchListener.openbutton();
}
} else {
if (!isOpen) {
if (dx < maxX / 2) {
BTmoveX = bWidth / 2;
isOpen = false;
} else {
BTmoveX = maxX + bWidth / 2;
isOpen = true;
firstState = true;
switchListener.openbutton();
}
} else {
if (Math.abs(dx) < maxX / 2 || dx > maxX / 2) {
BTmoveX = maxX + bWidth / 2;
isOpen = true;
} else {
BTmoveX = bWidth / 2;
isOpen = false;
firstState = false;
switchListener.closebutton();
}
}
}
if (firstState){
if (!isOpen){
switchListener.closebutton();
}
}else {
if (isOpen){
switchListener.openbutton();
}
}
invalidate();
break;
}
return true;
}
public void setOnSwitchListener(OnSwitchListener onSwitchListener) {
this.switchListener = onSwitchListener;
}
public interface OnSwitchListener {
void openbutton();
void closebutton();
}
}
用法:
<com.xie.brad.myswitchbutton.MyButton.SwitchButton
android:id="@+id/switchbutton"
android:layout_width="100dp"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
app:switch_state="true"/>
package com.xie.brad.myswitchbutton;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.widget.Toast;
import com.xie.brad.myswitchbutton.MyButton.SwitchButton;
public class MainActivity extends AppCompatActivity implements SwitchButton.OnSwitchListener {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
SwitchButton switchButton = (SwitchButton) findViewById(R.id.switchbutton);
switchButton.setOnSwitchListener(this);
}
@Override
public void openbutton() {
Toast.makeText(this,"开",Toast.LENGTH_SHORT).show();
}
@Override
public void closebutton() {
Toast.makeText(this,"关",Toast.LENGTH_SHORT).show();
}
}
代码写的蛮久了,最近闲暇,拿出来分享,代码比较乱,希望大家提出意见