赞
踩
看微信公众号的时候时常会想退出去回复消息,但又不想放弃已经阅读一半的文章,因为回复信息后再从公众号找到该篇文章之间有不必要的时间花费,微信悬浮窗的出现解决了这个烦恼,回复完消息之后只需要点击悬浮窗就可以回到之前在阅读的文章中。在对比多篇公众号文章的时候悬浮窗也使得在不同文章之间的切换更方便。悬浮窗的出现主要是为了省去用户在不同页面之间频繁切换时不必要的时间和精力的开销,这个组件小细节比较多,完整复刻估计需要分成三或四部分来讲,这篇文章主要讲述的是悬浮窗在点击前的按钮形态的实现,下一篇文章讲解按钮在不同形态之间切换,动起来。
先上最终效果对比图:
通过观察可得,悬浮按钮处于边缘的时候是属于不规则形状。属于官方的UI库中是不存在的不规则图形,也无法通过组合已有组件实现。这时候就需要用到Flutter提供的CustomPaint
和CustomPainter
来实现自绘组件,但具体的绘制工作是由Canvas
类和Paint
类进行的。
对微信的悬浮按钮进行分析后,发现微信悬浮按钮主要有三种形态:左边缘按钮形态,中心按钮形态,和右边缘按钮形态,而每一个形态在按下的时候会有一个阴影,表示已选中,松开的时候阴影消失,表示未选中。具体形态图解如下(按画布大小为50x50设计):
图解非一步到位,只是对原组件进行分析后大概画一下,在绘图的过程中再进行一些细微的调整达到较好的视觉效果(并非专业UI设计师,随便画画)。进行分析图解后,便可以着手对每一个形态进行绘制了。
在着手开始绘制前,我们需要了解我们绘制使用到的几个类:
构造函数如下:
- CustomPaint({
- Key key, this.painter, //背景画笔 this.foregroundPainter, //前景画笔 this.size = Size.zero, //画布即绘制区域的大小 this.isComplex = false, //是否为复杂绘制,若是Flutter则会启用一些缓存策略减少绘制的开销 this.willChange = false, //和isComplex配合使用,当启用缓存,表示下一帧中绘制是否会改变 Widget child, //子节点,可以为空})
CustomPainter
中定义的虚函数paint
,主要的绘制工作都是在这个函数中完成,主要定义如下:
void paint(Canvas canvas, Size size);
size: 表示绘制区域的大小,传递自CustomPaint
中的size
canvas: 画布,其内封装了大量的绘制方法,此处列举本文中用到方法:
API名称 | 功能 |
---|---|
drawCircle | 绘制圆形 |
drawPath | 绘制路径 |
drawImageRect | 根据给出的图片及原矩形(src)和目标矩形(dst)绘制图片 |
clipRRect | 根据给出的圆角矩形对画布进行剪裁(超出区域不绘制) |
drawShadow | 绘制阴影 |
drawColor | 根据模式绘制颜色(本文用于绘制图片背景填充颜色) |
如果说Canvas
是画布,那么Paint
就是画笔。Canvas
中封装的很多绘制方法都需要一个画笔参数去进行绘制。画笔Paint
中定义了一些画笔的基本属性,如画笔宽度,画笔颜色,笔触类型等,例子如下:
Paint _paint = Paint() ..color = Colors.blue //画笔颜色,此处为蓝色 ..strokeCap = StrokeCap.round //画笔笔触类型 ..isAntiAlias = true //是否启动抗锯齿 ..blendMode = BlendMode.exclusion //颜色混合模式 ..style = PaintingStyle.fill //绘画风格,默认为填充 ..colorFilter = ColorFilter.mode(Colors.blueAccent, BlendMode.exclusion) //颜色渲染模式 ..maskFilter = MaskFilter.blur(BlurStyle.inner, 3.0) //模糊遮罩效果 ..filterQuality = FilterQuality.high //颜色渲染模式的质量 ..strokeWidth = 15.0; //画笔的宽度
我们在实际使用中根据需要去选择相应的属性,并不需要全部初始化。
路径,使用drawPath
中绘制不规则图形可以通过函数或者点间连线、曲线等表示。本文用到的方法如下:
API名称 | 功能 |
---|---|
moveTo | 将路径起点移动到指定位置 |
lineTo | 从当前位置连线到指定位置 |
arcTo | 曲线 |
对于工程其他的文件和布局不做讨论,主要讨论如何实现继承CustomPainter
实现paint
方法的绘制,对于如何使用这个Painter,可以参考《Flutter实战》(https://book.flutterchina.club/chapter10/custom_paint.html)。
由于左右边缘按钮的图形绘制方法类似,因此我们主要讨论 左边缘按钮 的实现。由图解可知左边缘按钮是不规则的形状。我们的画布的尺寸为50x50,我们可以把这个形状看作一个圆形和一个正方形的重合,这是一种思路。
但我写的是另一种思路:看作是三条直线和一段圆弧所组成路径,以边缘按钮内层的具体代码实现为例:
//edgePath: 按钮外边缘路径,黑色线条 var edgePath = new Path() ..moveTo(size.width / 2, size.height); //移动去x轴中点(25,0) edgePath.lineTo(0.0, size.height); //第一条直线 edgePath.lineTo(0.0, 0.0);//第二条直线 edgePath.lineTo(size.width / 2,0.0);//第三条直线 //圆弧在圆心在(25,25),半径为25的圆上 Rect rect1 = Rect.fromCircle(center:Offset(size.w
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。