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

Exemple d'animation de chargement d'iQIYI en Android

This article introduces an example of an android simulation of iQIYI loading animation, the specific code is as follows:

Illustration:

knowledge points used:

  1. Path
  2. ValueAnimator

If you are not familiar with Path and ValueAnimator, it is recommended to read these great bloggers' blogs: the most suitable articles for custom views at the moment, detailed tutorials and practices for custom views, this is also a tutorial and practice, thank them for their efforts! (I hope everyone can read it carefully and get a lot of inspiration).

Animation breakdown

  1. A circle is first drawn counterclockwise slowly (the circle is not a closed circle)
  2. This step is a combination animation, the circle slowly disappears, and the triangle rotates counterclockwise

The difficulty here mainly lies in the calculation of coordinates, and I will explain it in detail next:

  1. Here, we take the center as the origin of the x, y axes, with the downward direction as the positive direction of the x-axis, and the right direction as the positive direction of the y-axis. If the size of the view is equal in width and height, at this time, the radius of the circle can be set to half of the width or height. If it is not equal in width and height, the minimum value of the width or height should be taken as half, as the radius of the circle.
  2. Next is the triangle, which is also a difficult point to determine the coordinates, this triangle is an equilateral triangle, we hope, when the triangle rotates, it also rotates around the center of the circle. Therefore, the distance from the center of the circle to each vertex of the triangle is equal. Here, I set the side length of the triangle to be half of the radius of the circle.

I believe this picture has been taken out, combined with the sine and cosine functions, p1,p2,p3the coordinates are also determined.

p1.x = -(int) ((radius / 2 * Math.tan(30 * Math.PI / 180)));
p1.y = -radius / 2;
p2.x = p1.x;
p2.y = radius / 2;
p3.x = (int) (radius / 2 / Math.sin(60 * Math.PI / 180));
p3.y = 0;

define some properties

private static final String DEFAULT_COLOR = "#00ba9b";
private static final int DEFAULT_SIZE = 50;  //default size
private static final int DRAW_CIRCLE = 10001; //marqueur d'état Dessiner le cercle et le triangle Exécuter l'animation de dessin du cercle
private static final int ROTATE_TRIANGLE = 10002; //marqueur d'état Exécuter l'animation de rotation du triangle et de rétractation du cercle
private Context mContext;
private Paint trianglePaint;  //pinceau du triangle
private Paint circlePaint;  //pinceau circulaire
private float paintStrokeWidth = 1; // définir la largeur du cercle
private long duration = 800; //durée d'exécution
private int mWidth; //largeur et hauteur de la Vue
private int mHeight;
private Path trianglePath; //chemin du triangle
private Path circlePath;  //chemin circulaire
private Path dst; //path calculé après pathMeasure
private Point p1, p2, p3; //trois points du triangle
private ValueAnimator animator; //animation des propriétés principalement pour obtenir 0-1valeur pour exécuter l'animation
private float mAnimatorValue = 0;  //stocker les valeurs obtenues 0-1la valeur
private int mCurrentState = 0;  //l'état actuel 
private int radius = 0; //rayon du cercle
private float startSegment; //longueur de départ du cercle dessiné
private PathMeasure mMeasure; //mesurer path
private int triangleColor = -1;
private int circleColor = -1;

définir path

1puisque le triangle est toujours présent, nous dessinons d'abord le triangle en utilisant le path, car nous connaissons déjà les coordonnées des trois sommets du triangle, le dessin du triangle devient donc très facile.

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();

de cette manière, le path du triangle est configuré, il suffit d'appeler canvans.drawPath() pour dessiner le triangle sur le canevas.

2.Puis vient le dessin du cercle, comme mentionné précédemment, le cercle a un trou, nous ajoutons également le cercle au path ici, car nous devons calculer la longueur du cercle après cela, ces opérations sont aidées par le path,


RectF circleRect = new RectF(-radius, -radius, radius, radius);
circlePath.addArc(circleRect, 268, 358); // ceci provient du cercle268° pour commencer à dessiner, dessiner258° pour laisser un espace de deux degrés

Configurer l'animation d'attribut

parce que l'animation nécessite un ensemble de 0-1des données
ici, nous utilisons les valeurs fournies par l'animation d'attribut pour réaliser l'animation.

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(); //ici, nous allons obtenir un 0-1la valeur
        invalidate(); // ici, on procède au redessin
      }
    });
    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) { 
       //Ici, la conversion d'état a lieu, exécutant différentes animations
        switch (mCurrentState) {
          case DRAW_CIRCLE:
            mCurrentState = ROTATE_TRIANGLE;
            break;
          case ROTATE_TRIANGLE:
            mCurrentState = DRAW_CIRCLE;
            break;
          default:
            break;
        }
      }
    });
  }

onDraw

Analyser la méthode onDraw

protected void onDraw(Canvas canvas) {
    super.onDraw(canvas);
    //Déplacer l'origine vers la position centrale
    canvas.translate(mWidth / 2, mHeight / 2);
    // Réinitialiser le path dst
    dst.reset();
    //Déterminer l'état actuel
    switch (mCurrentState) {
     //C'est là que nous parlons du premier état
      case DRAW_CIRCLE:
      //Cette ligne est pour obtenir la position de départ du path à tronquer (dst), en observant attentivement l'animation, on voit que le début du cercle est formé par une position vers
      //dessiné à partir des deux extrémités, cette position est environ le1/5Lorsque l'on atteint le point de départ du cercle, on commence à dessiner à partir du point de départ du cercle, j'exécute cette animation
      //Le temps est grossièrement réglé à 0-1 du 0.3à droite et à gauche de cette position.
        startSegment = (float) (mMeasure.getLength() / 5 * ((0.3 - mAnimatorValue) > 0 ? (0.3 - mAnimatorValue) : 0));
        //Il n'y a pas grand-chose ici, c'est juste pour dessiner un triangle
        trianglePaint.setStyle(Paint.Style.FILL_AND_STROKE);
        canvas.drawPath(trianglePath, trianglePaint);
        //Cette méthode est pour obtenir le segment que vous souhaitez tronquer, le premier paramètre est la position de départ, le deuxième paramètre est la position de fin, le troisième paramètre est
        //Le nombre est le segment de path tronqué ajouté à path (dst), attention, c'est un ajout et non un remplacement, donc il faut reset, le quatrième paramètre est
        //Doit-on déplacer le point de départ vers le point de départ de la voie actuelle tout en maintenant la voie dans dst inchangée (par exemple, si dst contient déjà un path, ici
        //Défini à false, cela garantit la continuité de dst et déplace le point de départ de la voie ajoutée après le déplacement de dst vers la fin de la dernière voie, ce qui garantit la continuité.
        mMeasure.getSegment(startSegment, mMeasure.getLength()) * mAnimatorValue, dst, true);
        canvas.drawPath(dst, circlePaint);
        break;
         //Deuxième animation
      case ROTATE_TRIANGLE:
      //Sauvegarder le canevas, car nous devons exécuter deux animations, sauvegarder l'état initial du canevas
        canvas.save();
        //Ensuite, effectuez d'abord la rotation du triangle
        trianglePaint.setStyle(Paint.Style.FILL_AND_STROKE);
        canvas.rotate(360 * mAnimatorValue);
        canvas.drawPath(trianglePath, trianglePaint);
        //Restaurer le canevas
        canvas.restore();
        //Ensuite, la disparition de l'anneau extérieur, la disparition est en fait la même que le dessin d'un cercle, ici nous avons un ensemble de 0-1la valeur variant, nous n'avons besoin que de
        //Lorsque vous coupez un segment, laissez le point de départ se rapprocher constamment de la longueur totale, ce qui entraînera un effet de disparition
        mMeasure.getSegment(mMeasure.getLength(), * mAnimatorValue, mMeasure.getLength(), dst, true);
        canvas.drawPath(dst, circlePaint);
        break;
      default:
        break;
    }
  }

Voici la totalité du contenu de cet article, j'espère qu'il vous aidera dans vos études, et j'espère que vous soutiendrez également le tutoriel criant.

Déclaration : le contenu de cet article est extrait du réseau, propriété du propriétaire original, contribué et téléversé par les utilisateurs d'Internet de manière spontanée. Ce site n'est pas propriétaire des droits d'auteur, n'a pas été traité par l'éditeur humain et n'assume aucune responsabilité juridique connexe. Si vous trouvez du contenu présumé de violation de droits d'auteur, veuillez envoyer un e-mail à : notice#oldtoolbag.com (veuillez remplacer # par @ lors de l'envoi d'un e-mail pour signaler une violation, et fournir des preuves pertinentes. Une fois vérifié, ce site supprimera immédiatement le contenu présumé de violation de droits d'auteur.)

Vous pourriez aimer