Android自定义加载圈动画效果
程序员文章站
2023-12-01 17:13:40
本文实例为大家分享了android自定义加载圈动画展示的具体代码,供大家参考,具体内容如下
实现如下效果:
该效果图主要有3个动画:
1.旋转动画...
本文实例为大家分享了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); } }
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。