English | 简体中文 | 繁體中文 | Русский язык | Français | Español | Português | Deutsch | 日本語 | 한국어 | Italiano | بالعربية

Ejemplo de animación de carga de iQIYI en Android

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:

  1. Path
  2. ValueAnimator

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

  1. Un círculo se dibuja lentamente en sentido horario (el círculo no es un círculo cerrado)
  2. Este paso es un animación compuesta, el círculo desaparece lentamente, al mismo tiempo que el triángulo gira en sentido horario

El punto difícil aquí reside principalmente en el cálculo de las coordenadas, y a continuación hablaré en detalle sobre esto:

  1. Aquí configuramos el centro como el punto de partida del eje x, y, en la dirección hacia abajo es el sentido positivo del eje x, hacia la derecha es el sentido positivo del eje y. Si se configura el tamaño de la vista como igual en anchura y altura, en este caso se puede configurar el radio del círculo como la mitad de la anchura o la altura. Si no es igual en anchura y altura, se debe tomar la mitad del valor mínimo entre la anchura y la altura como el radio del círculo.
  2. A continuación, es el triángulo, también es el punto difícil para determinar las coordenadas, este triángulo es un triángulo equilátero, queremos que, cuando el triángulo gire, también lo haga alrededor del centro del círculo. Por lo tanto, la distancia desde el centro del círculo a cada uno de los vértices del triángulo es igual. Aquí he configurado que el lado del triángulo es la mitad del radio del círculo.

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.

Te gustará