English | 简体中文 | 繁體中文 | Русский язык | Français | Español | Português | Deutsch | 日本語 | 한국어 | Italiano | بالعربية
Este artículo introduce un ejemplo de animación de carga similar a iQIYI en Android, el código específico es el siguiente:
Efecto visual:
Puntos de conocimiento utilizados:
Si no está familiarizado con Path y ValueAnimator, se recomienda ver estos grandes blogs: Artículos más adecuados para mí sobre cómo crear vistas personalizadas, Tutorial detallado sobre cómo crear vistas personalizadas y práctica, también es un tutorial y práctica, ¡gracias por su contribución! (Espero que puedan leerlo con atención y obtener muchas ideas).
Descomposición de la animación
El punto difícil aquí reside principalmente en el cálculo de las coordenadas, y a continuación hablaré en detalle sobre esto:
espero que esta imagen se haya presentado, combinando las funciones seno y coseno, p1,p2,p3las coordenadas también se obtuvieron.
p1.x = -(int) ((radio / 2 * Math.tan(30 * Math.PI / 180)));
p1.y = -radio / 2;
p2.x = p1.x;
p2.y = radio / 2;
p3.x = (int) (radio / 2 / Math.sin(60 * Math.PI / 180));
p3.y = 0;
definir algunas propiedades
private static final String DEFAULT_COLOR = "#00ba9b"; private static final int DEFAULT_SIZE = 50; //tamaño predeterminado private static final int DRAW_CIRCLE = 10001; //marca de estado Dibujar el círculo y el triángulo Ejecutar la animación de dibujo del círculo private static final int ROTATE_TRIANGLE = 10002; //marca de estado Ejecutar la animación de rotación del triángulo y de recuperación del círculo private Context mContext; private Paint trianglePaint; //pincel del triángulo private Paint circlePaint; //pincel circular private float paintStrokeWidth = 1; // establecer el ancho del círculo private long duration = 800; //el tiempo de ejecución private int mWidth; //las dimensiones de View private int mHeight; private Path trianglePath; //la ruta del triángulo private Path circlePath; //la ruta circular private Path dst; //por el pathMeasure calculado después de path private Point p1, p2, p3; //los tres puntos del triángulo private ValueAnimator animator; //animación de propiedad principalmente obtener 0-1para ejecutar la animación private float mAnimatorValue = 0; //almacenar el valor obtenido de 0-1el valor private int mCurrentState = 0; //el estado actual private int radius = 0; //el radio del círculo private float startSegment; //la longitud de inicio del círculo private PathMeasure mMeasure; //medir path private int triangleColor = -1; private int circleColor = -1;
establecer path
1.Ya que el triángulo siempre existe, primero dibujamos el triángulo, usando path para dibujar, ya que sabemos las coordenadas de los tres vértices del triángulo, dibujar el triángulo se vuelve muy fácil.
trianglePath = new Path(); p1 = new Point(); p2 = new Point(); p3 = new Point(); trianglePath.moveTo(p1.x, p1.y); trianglePath.lineTo(p2.x, p2.y); trianglePath.lineTo(p3.x, p3.y); trianglePath.close();
así que el path del triángulo se ha configurado, solo hay que llamar a canvans.drawPath() para dibujar el triángulo en la lienzo.
2.Luego es dibujar el círculo, como se mencionó anteriormente, el círculo tiene un hueco, aquí también agregamos el círculo al path, la razón por la que no lo dibujamos directamente en el canvas es porque luego vamos a calcular el perímetro del círculo, estas operaciones las realiza el path,
circlePath = new Path(); RectF circleRect = new RectF(-radio, -radio, radio, radio); circlePath.addArc(circleRect, 268, 358); // esto es desde el círculo268°comenzar a dibujar, dibujar258°dejar un hueco de dos grados
configurar la animación de atributos
debido a que la animación necesita un grupo de 0-1de los datos
aquí utilizamos los valores proporcionados por la animación de atributos para realizar la animación.
private void initAnimation() { TimeInterpolator timeInterpolator = new AccelerateDecelerateInterpolator(); animator = ValueAnimator.ofFloat(0, 1).setDuration(duration); animator.setInterpolator(timeInterpolator); animator.setRepeatMode(ValueAnimator.RESTART); animator.setRepeatCount(ValueAnimator.INFINITE); animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { @Override public void onAnimationUpdate(ValueAnimator animation) { mAnimatorValue = (float) animation.getAnimatedValue(); //aquí vamos a obtener un 0-1el valor invalidate(); // aquí se realiza el redibujo } }); animator.addListener(new Animator.AnimatorListener() { @Override public void onAnimationStart(Animator animation) { } @Override public void onAnimationEnd(Animator animation) { } @Override public void onAnimationCancel(Animator animation) { } @Override public void onAnimationRepeat(Animator animation) { //Aquí se realiza la transición de estado, ejecutando diferentes animaciones switch (mCurrentState) { case DRAW_CIRCLE: mCurrentState = ROTATE_TRIANGLE; break; case ROTATE_TRIANGLE: mCurrentState = DRAW_CIRCLE; break; default: break; } } }); }
onDraw
Análisis del método onDraw
protected void onDraw(Canvas canvas) { super.onDraw(canvas); //Mover el origen al centro de la posición canvas.translate(mWidth / 2, mHeight / 2); // Restablecer path dst dst.reset(); //Determinar el estado actual switch (mCurrentState) { //Aquí es el primer estado del que hablamos case DRAW_CIRCLE: //Esta línea es para obtener la posición de inicio del path (dst) que se necesita cortar, observando la animación con atención, el inicio de la circunferencia es una posición que se mueve //dibujando en los extremos, esta posición es aproximadamente la mitad de la circunferencia del1/5Cuando se llega al punto de partida de la circunferencia, se comienza a dibujar desde el punto de partida de la circunferencia, ejecuto esta animación //El tiempo se configura aproximadamente a 0-1 del 0.3de la posición de izquierda a derecha. startSegment = (float) (mMeasure.getLength() / 5 * ((0.3 - mAnimatorValue) > 0 ? (0.3 - mAnimatorValue) : 0)); //Aquí no hay nada, es solo para dibujar un triángulo trianglePaint.setStyle(Paint.Style.FILL_AND_STROKE); canvas.drawPath(trianglePath, trianglePaint); //Este método es para obtener el segmento que desea cortar, el primer parámetro es la posición de inicio, el segundo parámetro es la posición de finalización, el tercer parámetro es //El número es el path cortado, se agrega a path (dst), note que es agregar no reemplazar, por lo que debe resetearse, el cuarto parámetro es //¿Desea mover el punto de partida al punto de partida de la ruta actual para mantener inalterada la ruta en dst? (Por ejemplo, si dst tenía un path anteriormente, aquí //Estableció false, lo que asegura la continuidad de dst y mueve el punto de partida de la ruta añadida después de mover dst al final de la última ruta, manteniendo así la continuidad) mMeasure.getSegment(startSegment, mMeasure.getLength()) * mAnimatorValue, dst, true); canvas.drawPath(dst, circlePaint); break; //Segunda animación case ROTATE_TRIANGLE: //Guardar el lienzo, ya que se ejecutarán dos animaciones, guardar el estado inicial del lienzo canvas.save(); //Luego ejecuta primero la rotación del triángulo trianglePaint.setStyle(Paint.Style.FILL_AND_STROKE); canvas.rotate(360 * mAnimatorValue); canvas.drawPath(trianglePath, trianglePaint); //Restaurar el lienzo canvas.restore(); //Luego es la desaparición del círculo exterior, la desaparición es igual a la lógica de dibujar un círculo, aquí tenemos un grupo de 0-1El valor que cambia, solo necesitamos //Al cortar el segmento, hacer que el punto de partida se acerque constantemente a la longitud total, aparecerá el efecto de desaparición mMeasure.getSegment(mMeasure.getLength(), * mAnimatorValue, mMeasure.getLength(), dst, true); canvas.drawPath(dst, circlePaint); break; default: break; } }
Esto es todo el contenido de este artículo, espero que sea útil para su aprendizaje y que todos los amigos nos apoyen en el tutorial de clamor.
Declaración: Este artículo se ha obtenido de la red, el copyright pertenece al autor original, el contenido se contribuye y carga espontáneamente por los usuarios de Internet, este sitio web no posee los derechos de propiedad, no se ha procesado editorialmente y no asume responsabilidades legales relacionadas. Si encuentra contenido sospechoso de copyright, le invitamos a enviar un correo electrónico a: notice#w, proporcionando evidencia relevante.3Declaración: El contenido de este artículo se obtiene de la red, el copyright pertenece al autor original, el contenido se contribuye y carga espontáneamente por los usuarios de Internet, este sitio web no posee los derechos de propiedad, no se ha procesado editorialmente y no asume responsabilidades legales relacionadas. Si encuentra contenido sospechoso de copyright, le invitamos a enviar un correo electrónico a: notice#w, proporcionando evidencia relevante, una vez verificada, este sitio eliminará inmediatamente el contenido sospechoso de infracción.