欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  移动技术

Android自定义加载圈动画效果

程序员文章站 2023-12-01 17:13:40
本文实例为大家分享了android自定义加载圈动画展示的具体代码,供大家参考,具体内容如下 实现如下效果: 该效果图主要有3个动画: 1.旋转动画...

本文实例为大家分享了android自定义加载圈动画展示的具体代码,供大家参考,具体内容如下

实现如下效果:

Android自定义加载圈动画效果

该效果图主要有3个动画:
1.旋转动画
2.聚合动画
3.扩散动画

以上3个动画都是通过valueanimator来实现,配合自定义view的ondraw()方法实现不断的刷新和绘制界面.

具体代码如下:

package blog.csdn.net.mchenys.myanimationloading;

import android.animation.animator;
import android.animation.animatorlisteneradapter;
import android.animation.valueanimator;
import android.content.context;
import android.graphics.canvas;
import android.graphics.color;
import android.graphics.paint;
import android.graphics.pointf;
import android.util.attributeset;
import android.view.view;
import android.view.animation.linearinterpolator;
import android.view.animation.overshootinterpolator;

/**
 * created by mchenys on 2016/5/21.
 */
public class animationloading extends view {
  private float mbigcircleraduis = 90;//大圆的半径
  private float msubcircleradius = 20;//小圆的半径
  private pointf mbigcenterpoint;//大圆的圆心坐标
  private paint mbgpaint;//绘制背景的画笔
  private paint mfgpaint;//绘制前景色的画笔
  private animatortemplet mtemplet;//动画模板
  float mbigcirclerotateangle;//大圆旋转的角度
  float mdiagonaldist;//屏幕对角线一半的距离
  float mbgstrokecircleradius;//用于作为绘制背景空心圆的半径
  //6个小圆的颜色
  private int[] colors = new int[]{color.red, color.dkgray, color.yellow, color.blue, color.ltgray, color.green};

  public animationloading(context context) {
    this(context, null);
  }

  public animationloading(context context, attributeset attrs) {
    super(context, attrs);
    init();
  }

  @override
  protected void onsizechanged(int w, int h, int oldw, int oldh) {
    super.onsizechanged(w, h, oldw, oldh);
    //确定大圆的圆心坐标
    mbigcenterpoint.x = w / 2f;
    mbigcenterpoint.y = h / 2f;
    //屏幕对角线的一半
    mdiagonaldist = (float) (math.sqrt(w * w + h * h) / 2);
  }

  private void init() {
    mbigcenterpoint = new pointf();
    mfgpaint = new paint();
    mfgpaint.setantialias(true);
    mbgpaint = new paint(mfgpaint);
    mbgpaint.setcolor(color.white);
    mbgpaint.setstyle(paint.style.stroke);

  }

  @override
  protected void ondraw(canvas canvas) {
    if (null == mtemplet) {
      //开启旋转动画
      mtemplet = new rotatestate();
    }
    //传递canvas对象
    mtemplet.drawstate(canvas);
  }

  /**
   * 绘制圆
   *
   * @param canvas
   */
  private void drawcircle(canvas canvas) {
    //获取每个小圆间隔的角度
    float rotateangle = (float) (2 * math.pi / colors.length);
    for (int i = 0; i < colors.length; i++) {
      //每个小圆的实际角度
      double angle = rotateangle * i + mbigcirclerotateangle; //这里加上大圆旋转的角度是为了带动小圆一起旋转
      //计算每个小圆的圆心坐标
      float cx = (float) (mbigcircleraduis * math.cos(angle)) + mbigcenterpoint.x;
      float cy = (float) (mbigcircleraduis * math.sin(angle)) + mbigcenterpoint.y;
      //绘制6个小圆
      mfgpaint.setcolor(colors[i]);
      canvas.drawcircle(cx, cy, msubcircleradius, mfgpaint);
    }
  }

  /**
   * 绘制背景
   *
   * @param canvas
   */
  private void drawbackground(canvas canvas) {
    if (mbgstrokecircleradius > 0f) {
      //不断扩散的空心圆,空心圆的半径为屏幕对角线的一半,空心圆的线宽则从线宽一半到0
      float strokewidth = mdiagonaldist - mbgstrokecircleradius;//线宽从对角线的1/2 ~ 0
      mbgpaint.setstrokewidth(strokewidth);
      float radius = mbgstrokecircleradius + strokewidth / 2;//半径从对角线的1/4 ~ 1/2
      canvas.drawcircle(mbigcenterpoint.x, mbigcenterpoint.y,radius , mbgpaint);
    } else {
      //绘制白色背景
      canvas.drawcolor(color.white);

    }
  }

  private abstract class animatortemplet {
    abstract void drawstate(canvas canvas);

  }

  /**
   * 绘制旋转动画
   */
  private class rotatestate extends animatortemplet {
    valueanimator mvalueanimator;

    public rotatestate() {
      //旋转的过程,就是不断的获取大圆的角度,从0-2π
      mvalueanimator = valueanimator.offloat(0, (float) math.pi * 2);
      mvalueanimator.setinterpolator(new linearinterpolator());//匀速插值器
      mvalueanimator.setduration(1200);
      mvalueanimator.addupdatelistener(new valueanimator.animatorupdatelistener() {
        @override
        public void onanimationupdate(valueanimator animation) {
          //获取大圆旋转的角度
          mbigcirclerotateangle = (float) animation.getanimatedvalue();
          //重绘
          invalidate();
        }
      });
      mvalueanimator.setrepeatcount(valueanimator.infinite);//无限循环
      mvalueanimator.start();
    }

    /**
     * 停止旋转动画,在数据加载完毕后供外部调用
     */
    public void stoprotate() {
      mvalueanimator.cancel();
    }

    @override
    void drawstate(canvas canvas) {
      drawbackground(canvas);
      drawcircle(canvas);
    }
  }

  /**
   * 绘制聚合动画
   */
  private class mergingstate extends animatortemplet {

    public mergingstate() {
      //聚合的过程,就是不断的改变大圆的半径,从mbigcircleraduis~0
      valueanimator valueanimator = valueanimator.offloat(mbigcircleraduis, 0);
      valueanimator.setinterpolator(new overshootinterpolator(10f));//弹性插值器
      valueanimator.setduration(600);
      valueanimator.addupdatelistener(new valueanimator.animatorupdatelistener() {
        @override
        public void onanimationupdate(valueanimator animation) {
          //获取大圆变化的半径
          mbigcircleraduis = (float) animation.getanimatedvalue();
          //重绘
          invalidate();
        }
      });
      valueanimator.addlistener(new animatorlisteneradapter() {
        @override
        public void onanimationend(animator animation) {
          //聚合执行完后进入下一个扩散动画
          mtemplet = new spreadstate();

        }
      });
      valueanimator.start();
    }

    @override
    void drawstate(canvas canvas) {
      drawbackground(canvas);
      drawcircle(canvas);
    }
  }

  /**
   * 绘制扩散动画
   */
  private class spreadstate extends animatortemplet {

    public spreadstate() {
      //扩散的过程,就是不断的改变背景画绘制空心圆的半径,从0~mdiagonaldist
      valueanimator valueanimator = valueanimator.offloat(0, mdiagonaldist);
      valueanimator.setduration(600);
      valueanimator.addupdatelistener(new valueanimator.animatorupdatelistener() {
        @override
        public void onanimationupdate(valueanimator animation) {
          //获取大圆变化的半径
          mbgstrokecircleradius = (float) animation.getanimatedvalue();
          //重绘
          invalidate();
        }
      });

      valueanimator.start();
    }

    @override
    void drawstate(canvas canvas) {
      drawbackground(canvas);
    }
  }

  /**
   * 停止加载动画
   */
  public void stoploading() {
    if (null != mtemplet && mtemplet instanceof rotatestate) {
      ((rotatestate) mtemplet).stoprotate();
      //开启下一个聚合动画
      post(new runnable() {
        @override
        public void run() {
          mtemplet = new mergingstate();
        }
      });
    }
  }
}

测试的activity

package blog.csdn.net.mchenys.myanimationloading;

import android.os.bundle;
import android.os.handler;
import android.support.v7.app.appcompatactivity;
import android.widget.framelayout;
import android.widget.imageview;

public class mainactivity extends appcompatactivity {

  @override
  protected void oncreate(bundle savedinstancestate) {
    super.oncreate(savedinstancestate);
    framelayout content = new framelayout(this);
    content.setonclicklistener(null);
    imageview bg = new imageview(this);
    bg.setimageresource(r.drawable.fg);
    bg.setscaletype(imageview.scaletype.fit_xy);
    content.addview(bg);
    final animationloading loading = new animationloading(this);
    content.addview(loading);
    setcontentview(content);

    new handler().postdelayed(new runnable() {
      @override
      public void run() {
        //3s后停止加载动画
        loading.stoploading();
      }
    },3000);
  }
}

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。