之前看到qq 的图片发送效果很酷炫,很吸引人,不过现在这个效果好像没有了。试了几次,决定试试实现。大致想了下,实现效果还不错

需要实现的效果

一图胜千言,看图如下:

怎样实现呢?

首先从图中看分两部分,一部分是进度条带光晕得效果。第二部分是圆圈扩散到整个图片,到显示完整图片的过程。接下来一步一步跟着代码分析实现。

1、绘制的范围包括图片显示都在圆角矩形内,所以首先要裁剪canvas到圆角矩形。

        val path = Path()canvas.save()path.addRoundRect(RectF(0f, 0f, width.toFloat(), height.toFloat()), round, round, Path.Direction.CW)canvas.clipPath(path)

先保存画布,save()到最后要canvas.restore()。因为显示图片,可以有两种选择,第一种:自己绘制图片,通过drawable得方式。第二种:继承ImageView 同时还可以获得ImageView提供的各种属性,scaleType之类。本质上ImageView也是通Drawable实现。IamgeView还帮我们处理了测量的狂傲,所以有什么理由不选择继承呢。然后绘制图片只有简单一行代码,再裁剪画布之后:

  super.onDraw(canvas)

2、绘制背景

可以看到效果图,图片在黑色半透明的下方。并且在最后显示出来。着一点都是跟canvas绘制背景相关的。不多说,先设置画笔。

    private var paint: Paint = Paint()paint.isAntiAlias = truepaint.color = getColor(R.color.bantouming)

背景怎么绘制,直接通过canvas.drawPaint方法即可实现。把paint的颜色绘制到整个画布。并且再图片后边绘制,所以在上方。

canvas.drawPaint(paint)

3、绘制进度

这里根据每一阶段状态的不同,通过三个状态值区分:

    companion object {private const val READY = 1private const val PROGRESS = 2private const val FINISH = 3}

为了方便的绘制,并且整个view是对称的。所以坐标点移动到view中心,非常有利于实现。

     canvas.save()canvas.translate(width / 2f, height / 2f)

当然最后别忘了canvas.restore() 。

在中间都好说了。先看百分比的实现。主要是drawText()的x,y比较不好掌握,不过搞明白基线之类的,就没问题了。

先看百分比的paint

    private val textPaint by lazy {Paint().apply {isAntiAlias = truestyle = Paint.Style.STROKEtextSize = dp2px(16f).toFloat()color = getColor(R.color.main_gray)}}

接下来绘制,这行代码可能比较长。需要优化,到这里就先别吐槽。有点偷懒。

可以看到根据文字的宽,高。来绘制的。高这里需要额外注意

textPaint.textHeight().div(2) - textPaint.descent()

需要减去textPiat.descent(),如果不减绘制会偏下。

  val text = "${progress}%"canvas.drawText(text, 0 - textPaint.measureText(text).div(2), textPaint.textHeight().div(2) - textPaint.descent(), textPaint)

4、绘制光晕

这算是实现比较疑难的地方。要注意3个地方:

  • 1.光晕的实现
  • 2.呼吸效果
  • 3.PorterDuffXmode 使用。

先看呼吸效果如何实现。可能简单的想到的是通过圆环实现。但这样挺麻烦的,如果通过两个圆叠加,并设置paint.xfermode(PorterDuff.Mode.DST_OUT)``,可实现把内部圆裁剪掉。关于怎么使用,请看之前的关于xfermode的文章。光晕的实现需要依赖shader,这里通过RadilGradient` 实现。具体用法也可看之前文章。

设置shader

     paint.setShader(RadialGradient(0f, 0f, outRadius, intArrayOf(Color.TRANSPARENT, Color.WHITE, Color.WHITE, Color.TRANSPARENT), floatArrayOf(0.1f, 0.4f, 0.8f, 1f), Shader.TileMode.CLAMP))

接下来的呼吸效果通过动画设置大圆半径的变化来实现。

canvas.drawCircle(0f, 0f, innRaduus + (outRadius - innRaduus) * animatorValue, paint)

完整代码如下

canvas.drawCircle(0f, 0f, innRaduus + (outRadius - innRaduus) * animatorValue, paint)
paint.setXfermode(PorterDuffXfermode(PorterDuff.Mode.DST_OUT))
paint.setShader(null)
paint.color = Color.WHITE
canvas.drawCircle(0f, 0f, innRaduus, paint)
paint.setXfermode(null)

如果仅仅是这样那么绘制出来中间喝一个黑洞。因为背景是透明的。所以这时候在绘制之前需要canvas.savlayer。如下

val sc = canvas.saveLayer(-outRadius, -outRadius, outRadius, outRadius, paint, Canvas.ALL_SAVE_FLAG)

保存的范围包括大圆小圆 最后要restore

canvas.restoreToCount(sc)

再加上animatorValue 从0到1的动画就完成PROGRES阶段的动画了。

5、绘制FINISH动画,揭露图片效果

同样这里也需要使用PorterDuff.Mode.DST_OUT,不过这里需要的是对整个圆角画布范围进行操作。DST 是canvas.drawPaint绘制的背景。SRC 是一整个圆角矩形对角线的一半为最大半径,从PROGRES 状态大圆的半径的范围,到最大范围的动画变化。如下:

   val sc = canvas.saveLayer(-width.div(2f), -height.div(2f), width.div(2f), height.div(2f), paint, Canvas.ALL_SAVE_FLAG)canvas.drawPaint(paint)val maxRadius = Math.sqrt(Math.pow(width.toDouble(), 2.0) + Math.pow(height.toDouble(), 2.0)).div(2)paint.xfermode = PorterDuffXfermode(PorterDuff.Mode.DST_OUT)paint.color = Color.WHITEcanvas.drawCircle(0f, 0f, (outRadius + (maxRadius - outRadius) * finishAnimValue).toFloat(), paint)paint.xfermode = nullcanvas.restoreToCount(sc)

动画的使用与交替。这一点比较简单的ValueAnimator的使用,设置属性,Listener即可。有兴趣可参考源码

Github: https://github.com/hewking/HaloImageProgressView


感谢大家能耐着性子看完啰里啰嗦的文章

在这里我也分享一份私货,自己收录整理的Android学习PDF+架构视频+面试文档+源码笔记,还有高级架构技术进阶脑图、Android开发面试专题资料,高级进阶架构资料帮助大家学习提升进阶,也节省大家在网上搜索资料的时间来学习,也可以分享给身边好友一起学习

如果你有需要的话,可以点赞+评论关注我,点击这里领取 Android学习PDF+架构视频+面试文档+源码笔记

Android开发:高仿QQ,发送图片时炫酷的加载效果相关推荐

  1. android开发百度地图坐标偏差,利用百度地图Android sdk高仿微信发送位置功能及遇到的问题...

    接触了百度地图开发平台半个月了,这2天试着模仿了微信给好友发送位置功能,对百度地图的操作能力又上了一个台阶 我在实现这个功能的时候,遇到一些困难,可能也是别人将会遇到的困难,特在此列出 1.在微信发送 ...

  2. Android实现高仿QQ附近的人搜索展示

    本文主要实现了高仿QQ附近的人搜索展示,用到了自定义控件的方法 最终效果如下 1.下面展示列表我们可以使用ViewPager来实现(当然如果你不觉得麻烦,你也可以用HorizontalScrollVi ...

  3. Android:高仿QQ头像截取升级版

    观看此篇文章前,请先阅读上篇文章:高仿QQ头像截取: 本篇之所以为升级版,是在截取头像界面添加了与qq类似的阴影层(裁剪区域以外的部分),且看效果图:   为了适应大家不同需求,这次打了两个包,及上图 ...

  4. 利用百度地图Android sdk高仿微信发送位置功能

    接触了百度地图开发平台半个月了,这2天试着模仿了微信给好友发送位置功能,对百度地图的操作能力又上了一个台阶    我在实现这个功能的时候,遇到一些困难,可能也是别人将会遇到的困难,特在此列出 1.在微 ...

  5. Android:高仿QQ头像截取

    花费了半天时间,把 仿QQ头像截取的方法整理了下,并制作了一个demo以供大家参考,基本上实现了qq中我的资料界面上(包括背景透明化,上滑标题栏显示,下拉隐藏等)的大致效果,先上图看效果吧: 支持的功 ...

  6. android 登录注册动画,Android开发(14)——动画实战:炫酷登录

    本节内容 1.第三方库实现虚化 2.添加输入框和按钮 3.按钮状态 4.键盘隐藏 5.监听焦点改变的事件 6.手臂旋转动画 7.手掌和手臂动画 Demo简介 1.做一个炫酷登录的界面. image.p ...

  7. android 判断webview加载成功,Android:如何检查使用webview.loadUrl时url的成功加载

    不幸的是,目前在WebView中没有简单的方法来确保页面上的所有内容都已成功加载.我们希望在未来的版本中提供更好的API.让我解释一下你现在可以做什么. 首先,为了检测阻止WebView连接服务器加载 ...

  8. 《ArcGIS Runtime SDK for Android开发笔记》——(13)、图层扩展方式加载Google地图...

    1.前言 http://mt2.google.cn/vt/lyrs=m@225000000&hl=zh-CN&gl=cn&x=420&y=193&z=9& ...

  9. H5仿抖音上下切换翻页动态加载效果

    只有五个页面实现动态加载翻页效果,网上查到都是用Swiper 不停的插入元素,导致页面内容越来越多致卡顿.这里就只用五个页面来轮翻显示,实现无限加载的效果. <!DOCTYPE html> ...

最新文章

  1. LeetCode Minimum Depth of Binary Tree
  2. 成功解决sklearn\preprocessing\label.py:151: DeprecationWarning: The truth value of an empty array is amb
  3. 【软件工程】关于计算机的一些问答与思考
  4. WCF服务开发与调用的完整示例
  5. ie传递给系统调用的数据区域太小_内存区域与内存溢出异常
  6. ajax实现浏览器前进后退-location.hash与模拟iframe
  7. switch语句php,PHPswitch 语句 - PHP教程
  8. UNIDAC如何驱动MSSQL2000
  9. PHP html 转换成PDF wkhtmltopdf HTML 转换成 PDF (JAVA C#都适用)
  10. lj245a引脚功能图_74HC245引脚图应用电路与中文资料
  11. Oracle 的 Round函数详解
  12. 提高网速软件测试简历,测试局域网网速的方法
  13. 【元宇宙经济学】元宇宙经济的四个特征
  14. java读取配置文件详解
  15. Maltego注册问题
  16. 内蒙古大学计算机考研复试分数线,内蒙古大学2016年考研复试分数线
  17. TikTok视频没播放,涨粉难?狠抓5点,TikTok运营so easy!
  18. BZOJ 1193--马步距离
  19. 发那科机器人请关闭电源_发那科FANUC机器人报警处理(中文)
  20. 火车票身份证号打码真的安全吗

热门文章

  1. 【Revit二次开发】元素(Element)
  2. php校园学校宿舍管理打分系统 php毕业设计题目课题选题 php毕业设计项目作品源码(1)功能模块概要
  3. Java 根据年月 获取当月最后一天
  4. 工作10年的一些感悟
  5. 【转载】文本自动生成研究进展与趋势
  6. 超分辨率重建SRCNN--Matlab 7.0中运行
  7. 语音处理:音频入门之基础概念总结
  8. CentOS系统主机每日巡检脚本
  9. 思必驰刚折戟上交所,出门问问冲刺港交所能成功么?
  10. 腾讯新闻基于Flink PipeLine模式的实践