自定义Loading大全之SwapLoading
2016-07-01 00:16
197 查看
那一月 我摇动所有的经筒 不为超度 只为触摸你的指尖
那一年 磕长头匍匐在山路 不为觐见 只为贴着你的温暖
那一世 转山转水转佛塔 不为修来生 只为途中与你相见
那一瞬,我飞升成仙,不为长生,只为佑你平安喜乐
还是老规矩,上效果图:
![](https://img-blog.csdn.net/20160630230931188)
源码请点击自定义LoadingView大全
今天的主角登场:
![](https://img-blog.csdn.net/20160630231815889)
有5个小圆,编号 a,b,c,d,e a顺时针向后面运动到b的位置,同时b顺时针运动到a的位置,依次类推运动到e,e顺时针运动到a的同时a运动到e形成一个闭环。
需要注意的是:a运动到b的轨迹是半圆。最开始我就踩了一个坑,把轨迹想成了二阶贝塞尔曲线,一直纠结曲线公式,弄得我头都大了。后来灵感一闪,我傻啊,为啥不用圆形轨迹,哈哈一下我就豁然开朗啦。
分析一下,是不是很清晰,然后开撸。
前面的一些构造函数就初始化就不讲了,省略onMeasure,onSizeChanged方法。注意需要在onSizeChanged方法中处理padding属性。
先来看一张简单的草稿图,图画得不好,见谅。
![](https://img-blog.csdn.net/20160630235128186)
我还是用 a,b,c,d,e来表示小球,a小球向上顺时针运动,轨迹所经过的圆弧为180~360:
mValueAnimator表示属性动画的值(0.0f~1.0f)
b小球所经过的圆弧为0~180度:
a,b小球所运动的半径为2小球之间的距离。那么我们简单的实现2个小球的运动轨迹。
![](https://img-blog.csdn.net/20160701000531039)
需要注意从b运动到c,b所经过的弧度为180~0:
c经过的弧度为0~-180度:
依次类推可以实现a,b,c,d小球的运动动画,小球a到e就非常简单了,注意运动半径是2*小球间距。
我这里贴出onDraw和startAnimator方法代码,以供参考:
onDraw方法:
startAnimator方法:
这样就实现了SwapLoading加载动画。
敬请关注github源码地址
那一年 磕长头匍匐在山路 不为觐见 只为贴着你的温暖
那一世 转山转水转佛塔 不为修来生 只为途中与你相见
那一瞬,我飞升成仙,不为长生,只为佑你平安喜乐
概述
我们经常会看到一些很简单又非常耐看的Loading加载动画,它们又是怎么用代码实现出来的呢?通过代码实现简单的Loading动画可以帮助我们学到很多东西,尤其是一些算法的运用,任何事情都是从繁到简,日积夜累,正所谓你看得多了你知道的也就多了。。。还是老规矩,上效果图:
源码请点击自定义LoadingView大全
今天的主角登场:
SwapLoading
开撸之前,我们来分析一下动画:有5个小圆,编号 a,b,c,d,e a顺时针向后面运动到b的位置,同时b顺时针运动到a的位置,依次类推运动到e,e顺时针运动到a的同时a运动到e形成一个闭环。
需要注意的是:a运动到b的轨迹是半圆。最开始我就踩了一个坑,把轨迹想成了二阶贝塞尔曲线,一直纠结曲线公式,弄得我头都大了。后来灵感一闪,我傻啊,为啥不用圆形轨迹,哈哈一下我就豁然开朗啦。
分析一下,是不是很清晰,然后开撸。
前面的一些构造函数就初始化就不讲了,省略onMeasure,onSizeChanged方法。注意需要在onSizeChanged方法中处理padding属性。
先来看一张简单的草稿图,图画得不好,见谅。
我还是用 a,b,c,d,e来表示小球,a小球向上顺时针运动,轨迹所经过的圆弧为180~360:
mRotationAngle = DEGREE_180 + mValueAnimator * DEGREE_180;
mValueAnimator表示属性动画的值(0.0f~1.0f)
b小球所经过的圆弧为0~180度:
mRotationAngle = DEGREE_180 - mValueAnimator * DEGREE_180;
a,b小球所运动的半径为2小球之间的距离。那么我们简单的实现2个小球的运动轨迹。
需要注意从b运动到c,b所经过的弧度为180~0:
mRotationAngle = DEGREE_180 - mValueAnimator * DEGREE_180;
c经过的弧度为0~-180度:
mNextRotationAngle = -mValueAnimator * DEGREE_180;
依次类推可以实现a,b,c,d小球的运动动画,小球a到e就非常简单了,注意运动半径是2*小球间距。
我这里贴出onDraw和startAnimator方法代码,以供参考:
onDraw方法:
@Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); mPaint.setColor(Color.WHITE); //绘制小球 for (int i = 0; i < BALL_NUM; i++) { if (i == mCurrentBallIndex && i != BALL_NUM - 1) { if (isClockwiseRotation(i)) { mRotationAngle = DEGREE_180 + mValueAnimator * DEGREE_180; mNextRotationAngle = mValueAnimator * DEGREE_180; } else { mRotationAngle = DEGREE_180 - mValueAnimator * DEGREE_180; mNextRotationAngle = -mValueAnimator * DEGREE_180; } } if (i == mCurrentBallIndex) { mPaint.setStyle(Paint.Style.FILL_AND_STROKE); mRotationX = (float) (ballSpacing * BALL_SPACING_RADIUS * Math.cos(Math.toRadians(mRotationAngle))); mRotationY = (float) (ballSpacing * BALL_SPACING_RADIUS * Math.sin(Math.toRadians(mRotationAngle))); if (i == BALL_NUM - 1) { getFirstAndLastAngle(); //最后一个小球 canvas.drawCircle((float) (centerX + 2 * ballSpacing * Math.cos(Math.toRadians(mNextRotationAngle))), (float) (centerY + 2 * ballSpacing * Math.sin(Math.toRadians(mNextRotationAngle))), ballRadius, mPaint); } else { canvas.drawCircle(centerX - mRadius + ballSpacing * (BALL_SPACING_RADIUS + i) + mRotationX, centerY + mRotationY, ballRadius, mPaint); } } if ((i + 1) % BALL_NUM == getNextBallIndex()) { mPaint.setStyle(Paint.Style.STROKE); mRotationX = (float) (ballSpacing * BALL_SPACING_RADIUS * Math.cos(Math.toRadians(mNextRotationAngle))); mRotationY = (float) (ballSpacing * BALL_SPACING_RADIUS * Math.sin(Math.toRadians(mNextRotationAngle))); if (i == BALL_NUM - 1) { getFirstAndLastAngle(); //第一个小球 canvas.drawCircle((float) (centerX + 2 * ballSpacing * Math.cos(Math.toRadians(mRotationAngle))), (float) (centerY + 2 * ballSpacing * Math.sin(Math.toRadians(mRotationAngle))), ballRadius, mPaint); } else { canvas.drawCircle(centerX - mRadius + ballSpacing * (BALL_SPACING_RADIUS + i) + mRotationX, centerY + mRotationY, ballRadius, mPaint); } } if (i != mCurrentBallIndex && i != getNextBallIndex()) { mPaint.setStyle(Paint.Style.STROKE); canvas.drawCircle(centerX - mRadius + ballSpacing * i, centerY, ballRadius, mPaint); } } // centerX - mRadius + ballSpacing*0.5f centerY }
startAnimator方法:
//开始动画 public void startAnimator() { post(new Runnable() { @Override public void run() { ValueAnimator animator = ValueAnimator.ofFloat(0f, 1.0f); animator.setDuration(5000); animator.setInterpolator(new LinearInterpolator()); animator.setRepeatMode(ValueAnimator.RESTART); animator.setRepeatCount(ValueAnimator.INFINITE); animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { @Override public void onAnimationUpdate(ValueAnimator animation) { mValueAnimator = (float) animation.getAnimatedValue(); postInvalidate(); } }); animator.addListener(new AnimatorListenerAdapter() { @Override public void onAnimationStart(Animator animation) { super.onAnimationStart(animation); mCurrentBallIndex = 0; } @Override public void onAnimationRepeat(Animator animation) { super.onAnimationRepeat(animation); mCurrentBallIndex = getNextBallIndex(); } }); animator.start(); } }); }
这样就实现了SwapLoading加载动画。
敬请关注github源码地址
相关文章推荐
- 导出数据在代码中加载-骨骼动画在cocos中加载
- 软件架构、鸡窝、软件架构师
- Android漂亮的UI库集合
- Zigbee Z‐STACK协议栈和TinyOS
- spring boot 学习笔记(007)pom.xml修改
- Fastjson 简明教程
- 手机号码归属地查询代码
- Centos7安装RocketMQ及配置测试
- 超融合架构真的完美吗?
- linux中service与chkconfig的替代者systemctl的简单介绍
- sqlserver行列转换
- object-c的代码例子
- 【GOF23设计模式】_策略模式_CRM中报价策略_GUI编程中布局管理器底层架构JAVA248
- (数据类型-Number直接量前的“-”)JavaScript权威指南笔记4.2
- 关联
- Python.Module.site
- Codeforces 474 D Flowers
- C#数组的笔记
- 栈与队列-等价表达式(数据结构基础 第3周)
- 读《数据结构》 5-6章[数组和广义表和树]