安卓自带togglenbutton实在不敢恭维,一般都自定义style放两张图片实现,不过都是简单规则图形,就直接画出来了。
效果图
public class RToggleButton extends View implements View.OnClickListener {
private final int DURATION = 200;
private Paint paint;
private RectF rect;
private int width = 42, height = 24;
private int openColor;
private int closeColor;
private int strokeWidth;
private boolean isOn;
private OnToggleChangeListener onToggleChangeListener;
private ValueAnimator animator;
private float leftX, rightX, centerX, currentX;
public RToggleButton(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init();
getBackground().mutate().setAlpha(4);
TypedArray array = context.obtainStyledAttributes(attrs, R.styleable.MyToggleButton, defStyleAttr, 0);
openColor = array.getColor(R.styleable.MyToggleButton_openColor, 0xff04ade5);
closeColor = array.getColor(R.styleable.MyToggleButton_closeColor, 0xffc6c6c6);
strokeWidth = array.getDimensionPixelSize(R.styleable.MyToggleButton_strokeWidth, 4);
isOn = array.getBoolean(R.styleable.MyToggleButton_isOpen, false);
array.recycle();
}
public RToggleButton(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public RToggleButton(Context context) {
this(context, null);
}
private void init() {
paint = new Paint();
paint.setAntiAlias(true);
rect = new RectF();
setOnClickListener(this);
}
public boolean isOn() {
return isOn;
}
//打开或关闭的方法
public void setIsOpen(boolean isOpen) {
//属性动画,前面一个圆圈从左移动到右或从右移动到左
if (isOpen) {
animator = ValueAnimator.ofFloat(leftX, rightX).setDuration(DURATION);
} else {
animator = ValueAnimator.ofFloat(rightX, leftX).setDuration(DURATION);
}
animator.setInterpolator(new LinearInterpolator());
animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
currentX = (float) animation.getAnimatedValue();
//位置大于一半时状态改为打开
if (currentX > centerX && !isOn) {
isOn = true;
} else if (currentX < centerX && isOn) {
isOn = false;
}
invalidate();
}
});
animator.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
super.onAnimationEnd(animation);
if (onToggleChangeListener != null) {
onToggleChangeListener.onChange(isOn);
}
}
});
animator.start();
}
public void setData(int openColor, int closeColor, boolean isOn) {
this.openColor = openColor;
this.closeColor = closeColor;
this.isOn = isOn;
}
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int heightMode = MeasureSpec.getMode(heightMeasureSpec);
int heightSize = MeasureSpec.getSize(heightMeasureSpec);
int widthMode = MeasureSpec.getMode(widthMeasureSpec);
int widthSize = MeasureSpec.getSize(widthMeasureSpec);
int w = 0, h = 0;
if (widthMode == MeasureSpec.EXACTLY) {
w = widthSize;
} else {
w = dp2px(width);
}
if (heightMode == MeasureSpec.EXACTLY) {
h = heightSize;
} else {
h = dp2px(height);
}
setMeasuredDimension(w, h);
}
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
width = w;
height = h;
rect.set(0, 0, width, height);
leftX = height / 2;
rightX = width - height / 2;
centerX = width / 2;
if (isOn) {
currentX = rightX;
} else {
currentX = leftX;
}
}
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
if (isOn) {
paint.setColor(openColor);
} else {
paint.setColor(closeColor);
}
//画背景框
canvas.drawRoundRect(rect, height / 2, height / 2, paint);
//画前面一个圆,圆心x坐标值根据属性动画得到
paint.setColor(0xffffffff);
canvas.drawCircle(currentX, height / 2, height / 2 - strokeWidth, paint);
}
private int dp2px(int dp) {
float density = getContext().getResources().getDisplayMetrics().density;
return (int) (dp * density + 0.5);
}
public void onClick(View v) {
//单击切换状态
setIsOpen(!isOn);
}
public void setOnToggleChangeListener(OnToggleChangeListener onToggleChangeListener) {
this.onToggleChangeListener = onToggleChangeListener;
}
/**
* 开关状态改变时回调
*/
public interface OnToggleChangeListener {
void onChange(boolean isOn);
}
}
attrs里自定义属性
<declare-styleable name="MyToggleButton">
<attr name="openColor" format="color" />
<attr name="closeColor" format="color" />
<attr name="isOpen" format="boolean" />
<attr name="strokeWidth" format="dimension" />
</declare-styleable>