Android 自定义圆形旋转进度条,仿微博头像加载效果
2017-08-05 19:31
656 查看
微博 App 的用户头像有一个圆形旋转进度条的加载效果,看上去效果非常不错,如图所示:
![](https://oscdn.geek-share.com/Uploads/Images/Content/201708/05/d2cdcbb009aa19fa449956c4b711a145)
据说 Instagram 也采用了这种效果。最近抽空研究了一下,最后实现的效果是这样:
![](https://oscdn.geek-share.com/Uploads/Images/Content/201708/05/47a541f35326010bcc7ff9840636c9b9)
基本上能模拟出个大概,代码量不大,来讲讲实现思路吧。
模拟一种动画效果,首先需要仔细分析其运作过程,找到其中的物理规律,从而确定实现方案。像这种运动速度较快的动画,一般不是很容易看清。可以先通过录屏软件,录取动画运作的过程,然后借助一些辅助工具放慢放大,比如 PS,反复重复播放几遍,基本上就能看出动画的运作规律了。
回到这里的加载效果,拆分开来,可以理解为画笔上的两层绘制和时间上的两段过程。时间上,很明显可以看出分为前 360 度和后 360 度,主要在画笔上:
1,单一完整的圆弧绘制。前 360 度,从 360 度的圆弧到 0 度圆弧的递减过程;后 360 度,从 0 度圆弧到 360 度圆弧的递增过程。
2,重复片段的圆弧绘制。前 360 度,从零开始,逐渐递增,直到多段填满圆周;后 360 度,反过来,逐渐递减,直到数量为零。
其他的就是细节的处理,后面具体实现时再提及,我们先来看看如何实现这两个核心流程的绘制。
由于这两个流程使用的画笔属性相同,所以使用一个 Paint 对象即可,这段代码没什么好讲的,就是一些初始化工作:
注意,与微博原图效果不同的是,我的效果图中使用到了渐变色圆环,这样效果更好看一些。使用 setShader() 方法可以给画笔设置渐变色,实现方式是:
Shader 子类有很多,这里使用的是线性渐变类 LinearGradient,由于需要使用 View 宽高,所以放在了 onSizeChanged() 函数里面。
核心计算和绘制工作都在 onDraw() 方法里面,看下这里的代码:
前面提到,动画在时间上分前后 360 度的两段过程,所以这里定义了一个 maxAngle 变量来定义时间的变化。可以看到,前后 360 度的绘制代码看上去差不多,但还是有很大区别的。需要理解的地方有:
1,多个小段圆弧可以利用画布旋转的方式轻松实现,也就是 canvas.rotate() 方法,上面代码中的 while 循环部分。这里有个细节处理,就是每段圆弧的弧度有个递增变化。
2,整个 View 给人的感觉有一种旋转的效果,为了实现这个效果,在每次绘制前,都增加了旋转的步骤,也就是这行代码:
其中 mRatio 表示整个动画结束时,View 相比初始状态时整体旋转的角度。 这里我设置的默认值是 60,值越大,动画执行时呈现出越快的旋转效果。大家可以修改源码,自己尝试一下。
3,还有一点就是,maxAngle 变量每次增量值的设置,一定要设置为相邻两段片段圆弧的间距弧度。这样做的目的是,保证每次绘制,片段圆弧都能有一个完整的递增或递减。否则,动画执行时,看上会发生视觉上的抖动效果。
基本上就是这样,代码量虽然不多,但是各种细节的处理还是耗费了很多时间调整。本来想使用一些图例展示一下每行代码的作用,但是太费时间了。如果感兴趣的,完全可以自己下载一下源码,修改试试看。
经过简单地封装,提取出一部分属性:
注意:中间的头像部分不是这里自定义 View 的内容,使用时可以自由填充内容。比如,看下我这里的使用方式,还是比较自由的:
源代码还是老样子,统一在 GitHub 上的自定义 View 集锦库里,地址如下。:
https://github.com/Mike-bel/android-custom-views
关于我:亦枫,博客地址:http://yifeng.studio/,新浪微博:IT亦枫
微信扫描二维码,欢迎关注我的个人公众号:安卓笔记侠
不仅分享我的原创技术文章,还有程序员的职场遐想
据说 Instagram 也采用了这种效果。最近抽空研究了一下,最后实现的效果是这样:
基本上能模拟出个大概,代码量不大,来讲讲实现思路吧。
模拟一种动画效果,首先需要仔细分析其运作过程,找到其中的物理规律,从而确定实现方案。像这种运动速度较快的动画,一般不是很容易看清。可以先通过录屏软件,录取动画运作的过程,然后借助一些辅助工具放慢放大,比如 PS,反复重复播放几遍,基本上就能看出动画的运作规律了。
回到这里的加载效果,拆分开来,可以理解为画笔上的两层绘制和时间上的两段过程。时间上,很明显可以看出分为前 360 度和后 360 度,主要在画笔上:
1,单一完整的圆弧绘制。前 360 度,从 360 度的圆弧到 0 度圆弧的递减过程;后 360 度,从 0 度圆弧到 360 度圆弧的递增过程。
2,重复片段的圆弧绘制。前 360 度,从零开始,逐渐递增,直到多段填满圆周;后 360 度,反过来,逐渐递减,直到数量为零。
其他的就是细节的处理,后面具体实现时再提及,我们先来看看如何实现这两个核心流程的绘制。
由于这两个流程使用的画笔属性相同,所以使用一个 Paint 对象即可,这段代码没什么好讲的,就是一些初始化工作:
mPaint = new Paint(); mPaint.setAntiAlias(true); mPaint.setStyle(Paint.Style.STROKE); mPaint.setStrokeWidth(mArcWidth); mPaint.setStrokeCap(Paint.Cap.ROUND);
注意,与微博原图效果不同的是,我的效果图中使用到了渐变色圆环,这样效果更好看一些。使用 setShader() 方法可以给画笔设置渐变色,实现方式是:
@Override protected void onSizeChanged(int w, int h, int oldw, int oldh) { super.onSizeChanged(w, h, oldw, oldh); ...... Shader shader = new LinearGradient(0f, 0f, mWidth, mHeight, mStartColor, mEndColor, Shader.TileMode.CLAMP); mPaint.setShader(shader); }
Shader 子类有很多,这里使用的是线性渐变类 LinearGradient,由于需要使用 View 宽高,所以放在了 onSizeChanged() 函数里面。
核心计算和绘制工作都在 onDraw() 方法里面,看下这里的代码:
@Override protected void onDraw(Canvas canvas) { if (maxAngle <= 360) { float angle = 0; canvas.rotate(mRatio * maxAngle / 360, mWidth / 2, mHeight / 2); canvas.drawArc(mRectF, maxAngle, 360 - maxAngle, false, mPaint); while (angle <= maxAngle) { float length = mArcRadian * angle / maxAngle; canvas.drawArc(mRectF, 0, length, false, mPaint); canvas.rotate(mArcSpacing, mWidth / 2, mHeight / 2); angle += mArcSpacing; } } else { float angle = 0; canvas.rotate(mRatio + mRatio * (maxAngle - 360) / 360, mWidth / 2, mHeight / 2); canvas.drawArc(mRectF, 0, maxAngle - 360, false, mPaint); canvas.rotate(maxAngle - 360, mWidth / 2, mHeight / 2); while (angle <= 720 - maxAngle) { float length = mArcRadian * angle / (720 - maxAngle); canvas.drawArc(mRectF, 0, length, false, mPaint); canvas.rotate(mArcSpacing, mWidth / 2, mHeight / 2); angle += mArcSpacing; } } if (maxAngle <= 720) { maxAngle += mArcSpacing; postInvalidateDelayed(30); } }
前面提到,动画在时间上分前后 360 度的两段过程,所以这里定义了一个 maxAngle 变量来定义时间的变化。可以看到,前后 360 度的绘制代码看上去差不多,但还是有很大区别的。需要理解的地方有:
1,多个小段圆弧可以利用画布旋转的方式轻松实现,也就是 canvas.rotate() 方法,上面代码中的 while 循环部分。这里有个细节处理,就是每段圆弧的弧度有个递增变化。
2,整个 View 给人的感觉有一种旋转的效果,为了实现这个效果,在每次绘制前,都增加了旋转的步骤,也就是这行代码:
canvas.rotate(mRatio * maxAngle / 360, mWidth / 2, mHeight / 2);
其中 mRatio 表示整个动画结束时,View 相比初始状态时整体旋转的角度。 这里我设置的默认值是 60,值越大,动画执行时呈现出越快的旋转效果。大家可以修改源码,自己尝试一下。
3,还有一点就是,maxAngle 变量每次增量值的设置,一定要设置为相邻两段片段圆弧的间距弧度。这样做的目的是,保证每次绘制,片段圆弧都能有一个完整的递增或递减。否则,动画执行时,看上会发生视觉上的抖动效果。
基本上就是这样,代码量虽然不多,但是各种细节的处理还是耗费了很多时间调整。本来想使用一些图例展示一下每行代码的作用,但是太费时间了。如果感兴趣的,完全可以自己下载一下源码,修改试试看。
经过简单地封装,提取出一部分属性:
<declare-styleable name="CircleLoadingView"> <attr name="circleStartColor" format="color|reference"/> <attr name="circleEndColor" format="color|reference"/> <attr name="circleArcWidth" format="integer|reference"/> <attr name="circleArcRadian" format="integer|reference"/> <attr name="circleArcSpacing" format="integer|reference"/> </declare-styleable>
注意:中间的头像部分不是这里自定义 View 的内容,使用时可以自由填充内容。比如,看下我这里的使用方式,还是比较自由的:
<RelativeLayout android:layout_width="200dp" android:layout_height="200dp" android:layout_centerInParent="true"> <com.yifeng.view.view.CircleLoadingView android:layout_width="match_parent" android:layout_height="match_parent" app:circleStartColor="#ffff00" app:circleEndColor="#ff0000" app:circleArcRadian="5" app:circleArcWidth="10" app:circleArcSpacing="10"/> <ImageView android:layout_width="match_parent" android:layout_height="match_parent" android:layout_margin="10dp" android:src="@mipmap/ic_avatar_default"/> </RelativeLayout>
源代码还是老样子,统一在 GitHub 上的自定义 View 集锦库里,地址如下。:
https://github.com/Mike-bel/android-custom-views
关于我:亦枫,博客地址:http://yifeng.studio/,新浪微博:IT亦枫
微信扫描二维码,欢迎关注我的个人公众号:安卓笔记侠
不仅分享我的原创技术文章,还有程序员的职场遐想
![](http://img.my.csdn.net/uploads/201704/03/1491189316_9110.jpg)
相关文章推荐
- Android 自定义View ProgressBarCircle,圆形进度条,仿微博图片加载
- Android 自定义View -- 圆形进度条,文字旋转
- Android 三种方式实现自定义圆形页面加载中效果的进度条
- Android自定义圆形加载进度条
- Android 三种方式实现自定义圆形页面加载中效果的进度条
- Android自定义带加载动画效果的环状进度条
- Android 三种方式实现自定义圆形页面加载中效果的进度条
- Android 三种方式实现自定义圆形页面加载中效果的进度条
- android自定义圆形进度条,实现动态画圆效果
- Android自定义View仿华为圆形加载进度条
- Android 自定义view实现进度条加载效果实例代码
- [原型设计]Axure8制作圆形旋转加载进度环和百分比效果
- Android 自定义圆形头像CircleImageView支持加载网络图片的实现代码
- 【Android自定义View实战】之自定义圆形头像CircleImageView支持加载网络图片
- Android 自定义View之仿华为圆形加载进度条
- Android提高篇之自定义dialog实现processDialog“正在加载”效果、使用Animation实现图片旋转
- 三种方式实现自定义圆形页面加载中效果的进度条,包含一个好看的Android UI
- Android 使用DisplayImageOptions加载头像 自定义圆形头像
- Android自定义圆形进度条,完成类似LOFTER效果
- Android自定义圆形进度条,完成类似LOFTER效果