这个笔记是为了巩固之前的Canvas知识
先看一下效果图
其实效果看上去很简单,原理也简单,分析一下:
- 使用Canvas画一个普通按钮,并在点击之后从矩形逐渐先缩放成两个半圆加上中间的矩形;
- 从两个半圆和中间矩形组成的形状,再次渐变成最终的圆,最后在圆上绘制转动的圆圈;
现在分析一下代码怎么写:
- Canvas绘制带圆角的矩形,需要使用
public void drawRoundRect(@NonNull RectF rect, float rx, float ry, @NonNull Paint paint) {
super.drawRoundRect(rect, rx, ry, paint);
}
其中的参数rx指x方向上的圆角半径,ry指y方向上的圆角半径
只需要在一段时间内,让这个圆角半径等于高度的1/2,就是半圆了
ValueAnimator的addUpdateListener可以监听在一段时间内,某个元素从开始到结束的变化,并返回这个变化的因子,这个circleAngle 就是圆角的变化因子,它从0(我这里默认不绘制带圆角),变化到view高度的1/2
/**
* 设置矩形过度到圆角矩形的动画
*/
private void startRoundCircleAnimation() {
animatorRectToRound = ValueAnimator.ofInt(0, mHeight / 2);
animatorRectToRound.setDuration(circleDuration);
animatorRectToRound.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
circleAngle = (int) animation.getAnimatedValue();
invalidate();
}
});
}
-
从圆角圆角矩形到圆的变换,先看图
这一段就是整个View的起始宽度,最终变换成一个圆,那么中间这一段就是要压缩掉的,两个半圆合成一个圆
/**
* 设置圆角矩形过度到圆的动画
*/
private void startRectRoundAnimation() {
animatorRoundToCircle = ValueAnimator.ofInt(0, defaultDistance);
animatorRoundToCircle.setDuration(duration);
animatorRoundToCircle.addListener(new Animator.AnimatorListener() {
@Override
public void onAnimationStart(Animator animation) {
}
@Override
public void onAnimationEnd(Animator animation) {
//矩形完全变成圆之后,再绘制loading圆圈
startDrawLoad = true;
disableClick = true;
}
@Override
public void onAnimationCancel(Animator animation) {
}
@Override
public void onAnimationRepeat(Animator animation) {
}
});
animatorRoundToCircle.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
circleDistance = (int) animation.getAnimatedValue();
int alpha = 255 - (circleDistance * 255) / defaultDistance;
textPaint.setAlpha(alpha);
invalidate();
}
});
}
这里代码直接是从圆角矩形压缩到了圆,没有做分开压缩;并且压缩过程中将字体也从不透明变到透明
- 绘制中间的圆圈,并旋转
/***
* 绘制加载圆圈
* @param canvas
*/
private void drawLoad(Canvas canvas) {
canvas.translate(mWidth / 2, mHeight / 2);
canvas.rotate(degree);
float r = mHeight / 3;
RectF rectf = new RectF(-r, -r, r, r);
canvas.drawArc(rectf, 0, loadingAnge, false, loadPaint);
}
旋转的原理:
循环的旋转画布,其实真正画的那个圆圈没有旋转,只是将后面的Canvas旋转了
drawArc就多说了,使用一个RectF来绘制扇形,扇形的最外边距就是这个矩形的外切线
注意:
注意旋转画布之前,需要将画布移动,再旋转画布才能生效
关于旋转画布
黄色部分是屏幕,蓝色部分为画布,红色为真正画的内容
canvas.translate(200, 100);
**注意:
- 旋转是针对于x和y坐标的(0,0)点的,x和y轴是会旋转的,
还有一个旋转方法是canvas.rotate(90,x,y);就是绕x,y点旋转 - 图片永远显示在canvas中的,图片相对于canvas是没有任何变化的**
canvas.rotate(90);