这是我参与11月更文挑战的第25天,活动详情查看:2021最后一次更文挑战 昨天简单的介绍了绘制开关的准备工作,以及一些初始化的工作,接下来,开始我们的绘制过程,怎么样把我们准备的好的画笔,形状绘制到画布上,然后形成我们想要的东西。也就是我们的onDraw();
@Override
protected void onDraw(Canvas canvas) {
int radius;//圆角
radius = backRect.height() / 2;
//画关闭
if (enable) {
//画关闭背景外框
closePaint.setColor(linearColor);
closePaint.setStyle(Paint.Style.STROKE);
closePaint.setStrokeWidth(strokeWidth);
canvas.drawRoundRect(lineCircleRect, radius, radius, closePaint);
//画关闭背景
closePaint.setColor(closeColor);
closePaint.setStyle(Paint.Style.FILL);
canvas.drawRoundRect(closeRect, radius, radius, closePaint);
} else {
//画关闭背景外框
closePaint.setColor(linearColor);
closePaint.setStyle(Paint.Style.STROKE);
closePaint.setStrokeWidth(strokeWidth);
canvas.drawRoundRect(lineCircleRect, radius, radius, closePaint);
//画关闭背景
closePaint.setColor(closeColor);
closePaint.setStyle(Paint.Style.FILL);
canvas.drawRoundRect(closeRect, radius, radius, closePaint);
//阴影
closePaint.setColor(Color.WHITE);
closePaint.setStyle(Paint.Style.FILL);
backCircleRect.set(backRect);
closePaint.setAlpha(disableAlpha);
canvas.drawRoundRect(backCircleRect, radius, radius, closePaint);
}
//画开启
openPaint.setColor(openColor);
openPaint.setAlpha(enableAlpha);
backCircleRect.set(backRect);
canvas.drawRoundRect(backCircleRect, radius, radius, openPaint);
//画不可用
openPaint.setColor(Color.WHITE);
openPaint.setAlpha(disableAlpha);
canvas.drawRoundRect(backCircleRect, radius, radius, openPaint);
//画小圆
frontRect.set(frontRectLeft, rimSize, frontRectLeft + backRect.height() - 2 * rimSize, backRect.height() - rimSize);
frontCircleRect.set(frontRect);
paintCircle.setColor(Color.WHITE);
paintCircle.setShadowLayer(strokeRound, 0, 0, linearColor);
canvas.drawRoundRect(frontCircleRect, radius, radius, paintCircle);
setLayerType(LAYER_TYPE_SOFTWARE, null);
}
}
接下来我们来绘制我们触摸事件,开和关的处理,点击事件,滑动事件
private boolean isActionMove = false;
private boolean slideable = false;//是否可以滑动
@SuppressLint("ClickableViewAccessibility")
@Override
public boolean onTouchEvent(MotionEvent event) {
if (!enable)
return super.onTouchEvent(event);
int action = MotionEventCompat.getActionMasked(event);
switch (action) {
case MotionEvent.ACTION_DOWN:
eventStartX = (int) event.getRawX();
break;
case MotionEvent.ACTION_MOVE:
if (slideable) {
eventLastX = (int) event.getRawX();
diffX = eventLastX - eventStartX;
int tempX = diffX + frontRectLeftBegin;
tempX = (tempX > maxLeft ? maxLeft : tempX);
tempX = (tempX < minLeft ? minLeft : tempX);
if (tempX >= minLeft && tempX <= maxLeft) {
frontRectLeft = tempX;
enableAlpha = (int) (255 * (float) tempX / (float) maxLeft);
isActionMove = true;
invalidateView();
}
}
break;
case MotionEvent.ACTION_UP:
sliderMove(event);
break;
case MotionEvent.ACTION_CANCEL:
if (isActionMove) {
sliderMove(event);
}
Log.e("onTouchEvent:", "ACTION_CANCEL");
break;
default:
break;
}
return true;
}
滑动处理
/***
* 执行滑动
* @param event
*/
private void sliderMove(MotionEvent event) {
int wholeX = (int) (event.getRawX() - eventStartX);
frontRectLeftBegin = frontRectLeft;
boolean toRight;
toRight = (frontRectLeftBegin > maxLeft / 2 ? true : false);
if (Math.abs(wholeX) < 3) {
toRight = !toRight;
}
moveToDest(toRight);
}
执行完一个绘制动作,需要刷新整个绘制的画布,重新绘制
/**
* 重新绘制
*/
private void invalidateView() {
if (Looper.getMainLooper() == Looper.myLooper()) {
invalidate();
} else {
postInvalidate();
}
}
执行切换操作动画,完成开和关的动画,透明度变化,切换监听回调
/***
* 切换操作
* @param toRight
*/
public void moveToDest(final boolean toRight) {
/****切换动画****/
ValueAnimator toDestAnim = ValueAnimator.ofInt(frontRectLeft, toRight ? maxLeft : minLeft);
toDestAnim.setDuration(300);
toDestAnim.setInterpolator(new AccelerateDecelerateInterpolator());
toDestAnim.start();
toDestAnim.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
setLayerType(LAYER_TYPE_NONE, null);
frontRectLeft = (Integer) animation.getAnimatedValue();
enableAlpha = (int) (255 * (float) frontRectLeft / (float) maxLeft);
invalidateView();
}
});
toDestAnim.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
if (toRight) {
isOpen = true;
frontRectLeftBegin = maxLeft;
enableAlpha = 255;
} else {
isOpen = false;
frontRectLeftBegin = minLeft;
enableAlpha = 0;
}
if (phSwitchButtonListener != null)
phSwitchButtonListener.onStatusChanged(PHSwitchButton.this, isOpen);
}
});
}
/***
* 设置监听
* @param listener
*/
public void setPHSwitchButtonListener(PHSwitchButtonListener listener) {
this.phSwitchButtonListener = listener;
}
一步一步来,写到哪里想到哪里,少什么补什么,对外公开滑动的监听,交给外部处理业务逻辑
总结
以上就是自定义的一个开关按钮的大部分内容,涉及到的东西也不是很多,分析清楚,就可以把大体的内容绘制出来。