prefacio
En primer lugar, echemos un vistazo a la animación de carga en Xiaomi, aunque es solo una imagen, porque no puede grabar todo, muchos de ellos tienen éxito tan pronto como se cargan, y no me dan cualquier posibilidad, así que solo estoy tomando una captura de pantalla, la característica de su animación de carga es que el círculo de la izquierda seguirá girando.
El efecto de imitación es el siguiente:
Proceso de implementación
Esto no es difícil, solo aprenda una fórmula, es decir, conozca el centro, el radio, el ángulo y encuentre las coordenadas del punto en el círculo. El resultado calculado puede dibujar un círculo sólido en este punto. El siguiente es un cuadro de diálogo personalizado , déjalo En la realidad inferior, la Vista también es personalizada.
class MiuiLoadingDialog(context: Context) : Dialog(context) {
private var miuiLoadingView : MiuiLoadingView= MiuiLoadingView(context);
init {
setContentView(miuiLoadingView)
setCancelable(false)
}
override fun show() {
super.show()
val window: Window? = getWindow();
val wlp = window!!.attributes
wlp.gravity = Gravity.BOTTOM
window.setBackgroundDrawable( ColorDrawable(Color.TRANSPARENT));
wlp.width=WindowManager.LayoutParams.MATCH_PARENT;
window.attributes = wlp
}
}
复制代码
La siguiente es la lógica principal. En él, primero clipPath
corte una forma con esquinas redondeadas a través del método y luego dibuje un círculo exterior, que es fijo.
El círculo en el medio requiere una fórmula, como sigue.
x1 = x0 + r * cos(a * PI /180 )
y1 = y0 + r * sin(a * PI /180 )
复制代码
x0 y y0 son los puntos centrales del círculo grande exterior, r es el tamaño del círculo pequeño en el medio, y a es el ángulo. Solo necesita seguir cambiando este ángulo, y el x1 y y1 obtenidos se pueden dibujar por dibujarCírculo.
class MiuiLoadingView @JvmOverloads constructor(
context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0
) : View(context, attrs, defStyleAttr) {
//Dialog上面圆角大小
val CIRCULAR: Float = 60f;
//中心移动圆位置
var rx: Float = 0f;
var ry: Float = 0f;
//左边距离
var MARGIN_LEFT: Int = 100;
//中心圆大小
var centerRadiusSize: Float = 7f;
var textPaint: Paint = Paint().apply {
textSize = 50f
color = Color.BLACK
}
var circlePaint: Paint = Paint().apply {
style = Paint.Style.STROKE
strokeWidth = 8f
isAntiAlias = true
color = Color.BLACK
}
var centerCirclePaint: Paint = Paint().apply {
style = Paint.Style.FILL
isAntiAlias = true
color = Color.BLACK
}
var degrees = 360;
val TEXT = "正在加载中,请稍等";
var textHeight = 0;
init {
var runnable = object : Runnable {
override fun run() {
val r = 12;
rx = MARGIN_LEFT + r * Math.cos(degrees.toDouble() * Math.PI / 180).toFloat()
ry =
((measuredHeight.toFloat() / 2) + r * Math.sin(degrees.toDouble() * Math.PI / 180)).toFloat();
invalidate()
degrees += 5
if (degrees > 360) degrees = 0
postDelayed(this, 1)
}
}
postDelayed(runnable, 0)
var rect = Rect()
textPaint.getTextBounds(TEXT, 0, TEXT.length, rect)
textHeight = rect.height()
}
override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
setMeasuredDimension(widthMeasureSpec, 220);
}
override fun onDraw(canvas: Canvas) {
super.onDraw(canvas)
var path = Path()
path.addRoundRect(
RectF(0f, 0f, measuredWidth.toFloat(), measuredHeight.toFloat()),
floatArrayOf(CIRCULAR, CIRCULAR, CIRCULAR, CIRCULAR, 0f, 0f, 0f, 0f), Path.Direction.CW
);
canvas.clipPath(path)
canvas.drawColor(Color.WHITE)
canvas.drawCircle(
MARGIN_LEFT.toFloat(), measuredHeight.toFloat() / 2,
35f, circlePaint
)
canvas.drawCircle(
rx, ry,
centerRadiusSize, centerCirclePaint
)
canvas.drawText(TEXT, (MARGIN_LEFT + 80).toFloat(), ((measuredHeight / 2)+(textHeight/2)).toFloat(), textPaint)
}
}
复制代码