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

Exemplo de animação de carregamento do爱奇艺 no Android

Este artigo introduz um exemplo de animação de carregamento de emulação do iQIYI para Android, o código específico é o seguinte:

Efeito visual:

Conhecimentos usados:

  1. Path
  2. ValueAnimator

Se você ainda não está familiarizado com Path e ValueAnimator, recomendo que você veja esses blogs de grandes gênios: Artigos mais adequados para mim sobre como criar view personalizados, Tutorial detalhado sobre como criar view personalizados e prática, este também é um tutorial e prática, obrigado pelo seu esforço! (Espero que você possa ler com atenção e obter muitas inspirações).

Animação desmontada

  1. Primeiro, desenhar lentamente um círculo no sentido horário (o círculo não é um círculo fechado)
  2. Este é um efeito animado composto, o círculo desaparece lentamente, enquanto o triângulo gira no sentido horário

O ponto difícil aqui é a cálculo das coordenadas, e eu vou explicar em detalhes a seguir:

  1. Aqui, usamos o centro como o ponto de origem do eixo x, y, a direção para baixo é o eixo x positivo, e a direção para a direita é o eixo y positivo. Se o tamanho do view for igual em largura e altura, neste momento, podemos configurar o raio do círculo como metade da largura ou altura. Se não for igual em largura e altura, deve-se pegar a metade do menor valor entre a largura e a altura como o raio do círculo.
  2. A seguir é o triângulo, que também é um dos pontos difíceis para determinar as coordenadas, este triângulo é um triângulo equilátero, desejamos que, quando o triângulo girar, ele também gire em torno do centro do círculo. Portanto, a distância do centro do círculo para cada vértice do triângulo é igual. Aqui, configurei o comprimento da aresta do triângulo como o raio do círculo.

espero que esta imagem tenha sido extraída, combinando as funções seno e cosseno, p1,p2,p3as coordenadas também são determinadas.

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;

definir algumas propriedades

private static final String DEFAULT_COLOR = "#00ba9b";
private static final int DEFAULT_SIZE = 50;  //tamanho padrão
private static final int DRAW_CIRCLE = 10001; //marca de estado Desenhar o círculo e o triângulo Executar a animação de desenho do círculo
private static final int ROTATE_TRIANGLE = 10002; //marca de estado Executar a animação de rotação do triângulo e de recuo do círculo
private Context mContext;
private Paint trianglePaint;  //pincel do triângulo
private Paint circlePaint;  //pincel circular
private float paintStrokeWidth = 1; // definir a largura do círculo
private long duration = 800; //tempo de execução
private int mWidth; //largura e altura da View
private int mHeight;
private Path trianglePath; //o caminho do triângulo
private Path circlePath;  //o caminho circular
private Path dst; //o path calculado pelo pathMeasure
private Point p1, p2, p3; //os três pontos do triângulo
private ValueAnimator animator; //animação de propriedade principalmente para obter 0-1usar o valor para executar a animação
private float mAnimatorValue = 0;  //armazenar os 0 obtidos-1o valor
private int mCurrentState = 0;  //o estado atual 
private int radius = 0; //o raio do círculo
private float startSegment; //a comprimento inicial do círculo desenhado
private PathMeasure mMeasure; //medir o path
private int triangleColor = -1;
private int circleColor = -1;

definir o path

1Porque o triângulo sempre existe, primeiro desenhamos o triângulo, usando o path para desenhar, já sabemos as coordenadas dos três vértices do triângulo, desenhar o triângulo torna-se 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();

Desta forma, o path do triângulo está configurado, basta chamar canvans.drawPath() para desenhar o triângulo na tela.

2. Em seguida, é desenhar a circunferência, como já mencionado, a circunferência tem um buraco, aqui também adicionamos a circunferência ao path, porque ainda precisamos calcular o comprimento da circunferência da circunferência, essas operações são ajudadas pelo path,

circlePath = new Path();
RectF circleRect = new RectF(-raio, -raio, raio, raio);
circlePath.addArc(circleRect, 268, 358); // isto é da circunferência da268°começar a desenhar, desenhar258°deixar um espaço de dois graus

configurar a animação de atributos

devido ao fato de que a animação precisa de um conjunto de 0-1dos dados
aqui usamos os valores fornecidos pela animação de atributos para realizar a animação.

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(); //aqui vamos obter um 0-1o valor
        invalidate(); // aqui é feita a redesenhar
      }
    });
    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) { 
       //Aqui ocorre a conversão de estado, executando diferentes animações
        switch (mCurrentState) {
          Aqui é o que chamamos de primeiro estado
            mCurrentState = ROTATE_TRIANGLE;
            break;
          case ROTATE_TRIANGLE:
            mCurrentState = DRAW_CIRCLE;
            break;
          default:
            break;
        }
      }
    });
  }

onDraw

Analisar o método onDraw

protected void onDraw(Canvas canvas) {
    super.onDraw(canvas);
    //Mover o origem para a posição central
    canvas.translate(mWidth / 2, mHeight / 2);
    // Resetar o caminho path dst
    dst.reset();
    //Determinar o estado atual
    switch (mCurrentState) {
     //Aqui é o primeiro estado mencionado
      Aqui é o que chamamos de primeiro estado
      //case DRAW_CIRCLE:
      //Esta linha é para obter a posição de início do caminho a ser cortado (dst), observando cuidadosamente a animação, o início da circunferência é uma posição que se move1/5desenhando nos extremos, essa posição é aproximadamente no centro da circunferência
      //, quando se chega ao ponto de início da circunferência, começa a desenhar a partir do ponto de início da circunferência, eu executei essa animação-1 do tempo é aproximadamente definido como 03da posição. A 0.
        startSegment = (float) (mMeasure.getLength() / 5 * ((0.3 - mAnimatorValue) > 0 ? (0.3 - mAnimatorValue) : 0));
        //Aqui não há nada, é apenas para desenhar um triângulo
        trianglePaint.setStyle(Paint.Style.FILL_AND_STROKE);
        canvas.drawPath(trianglePath, trianglePaint);
        //Este método é para obter o fragmento que você deseja cortar, o primeiro parâmetro é a posição de início, o segundo parâmetro é a posição de fim, o terceiro parâmetro
        //O número é o caminho cortado, adicionado ao caminho (dst), note que é adicionado e não substituído, portanto, antes é necessário resetar, o quarto parâmetro é
        //Deseja mover o ponto de início para o ponto de início da rota atual, mantendo inalterada a rota em dst (por exemplo, se antes dst tinha um path, aqui
        //Definido como falso, isso garante a contiguidade de dst ao mover o ponto de início da rota adicionada após dst, mantendo assim a contiguidade)
        mMeasure.getSegment(startSegment, mMeasure.getLength()) * mAnimatorValue, dst, true);
        canvas.drawPath(dst, circlePaint);
        break;
         //Segunda animação
      case ROTATE_TRIANGLE:
      //Salve o canvas, porque vamos executar duas animações, salve o estado inicial do canvas
        canvas.save();
        //Depois disso, execute primeiro a rotação do triângulo
        trianglePaint.setStyle(Paint.Style.FILL_AND_STROKE);
        canvas.rotate(360 * mAnimatorValue);
        canvas.drawPath(trianglePath, trianglePaint);
        //Restaurar o canvas
        canvas.restore();
        //Depois disso, é a vez do círculo externo desaparecer, o efeito de desaparecer é o mesmo que desenhar um círculo, aqui temos um grupo de 0-1do valor que muda, precisamos apenas
        //Quando cortamos um pedaço, fazemos com que o ponto de partida se aproxime constantemente da comprimento total, então aparecerá o efeito de desaparecer
        mMeasure.getSegment(mMeasure.getLength(), * mAnimatorValue, mMeasure.getLength(), dst, true);
        canvas.drawPath(dst, circlePaint);
        break;
      default:
        break;
    }
  }

Isso é tudo o que há no artigo, esperamos que ajude na sua aprendizagem e que você apoie mais o tutorial de clamor.

Declaração: O conteúdo deste artigo foi extraído da Internet, pertence ao respectivo autor, o conteúdo foi contribuído e carregado voluntariamente pelos usuários da Internet, este site não possui direitos de propriedade, não foi editado manualmente e não assume responsabilidades legais relacionadas. Se você encontrar conteúdo suspeito de violação de direitos autorais, por favor, envie um e-mail para: notice#w3Declaração: O conteúdo deste artigo foi extraído da Internet, pertence ao respectivo autor, o conteúdo foi contribuído e carregado voluntariamente pelos usuários da Internet, este site não possui direitos de propriedade, não foi editado manualmente e não assume responsabilidades legais relacionadas. Se você encontrar conteúdo suspeito de violação de direitos autorais, por favor, envie um e-mail para: notice#w

Você também pode gostar