本系列教程基于Flutter widget, 意在为Flutter 入门提供基础建设. 重点在讲解widget 的 用法,参数以及扩展.
适宜人群: 入门

引子

Banner 主要是一些提示性的文案, 往往被用于在 debug 模式或者在 assert 中用于信息的提示. 之所以介绍这个组件呢 ~ 是希望给大家日常开发中带来一些小思考和灵感. 毕竟谁也不知道设计的下一步思路是什么 ~

这里简单通过一个示例看一下大致的 ui , 方便大家对后续的讲解有个概念性认识.

1
2
3
4
5
6
7
8
9
Banner(
location: BannerLocation.bottomEnd,
message: 'banner',
child: Container(
height: 100,
width: 100,
color: Colors.blue,
),
)

这里我们通过 location、message 两个必填属性来简单写一下 Banner . location 的话即在 child 中的相对位置, message 即在 Banner 中所展示的信息, 如图:

image

很多人看到这个 ui 时, 第一句话可能会说:“ 这不是默认的 Flutter 以 debug 模式运行的右上角的标嘛! ”. 没错, 确实是这个标.

Banner 实际上作为一个 StatelessWidget 而被调用, 能如此完成一个奇怪的标识和它使用 CustomPaint 是有关系的, CustomPaint 理论上可以绘制出任何想像出的图案, 自然也包括了一个小小的 Banner. 让我们一起聚焦看看它是如何实现的吧?

BannerPainter

Banner 在 CustomPaint 中, 通过了 foregroundPainter 去绘制 Banner 自身. 这就归功于图层的概念, 让 Banner 作为前景来绘制. foregroundPainter 即 BannerPainter .

paint

具体的绘制流程在 BannerPainter 的 paiint 方法中,
image

首先, 在初始阶段, 会初始化部分值. 这个阶段会通过 _prepared 来判断是否已经初始化了一些字段. 在 _prepare 方法中, Painter 完成了 shadow、Paint、TextPainter 的初始化. 也就是阴影、画笔以及文字画笔. 在一切都初始化完后, 通过 Canvas 的平移、旋转 绘制矩形以及阴影. 完成了大体外壳的绘制. 最后, 通过 TextPainter 绘制需要展示的文字.

hitTest

我们可以看到它重写了 hitTest 方法, 因此 Banner 是不会命中点击事件的.

image

思考&&总结

通过 Banner 的角标绘制, 我们学习到了阴影、文字的绘制. 包括对 Canvas 对利用. 在日常中, 我们也可以通过这种方法, 给我们的widget 加上一些角标等等. 最有用的包括在头像上加入头饰等等. 相信大家的小脑袋瓜应该有很多想法了吧! 可以动手试试哦~

温习一下 :

  • shadow 的绘制

    1
    2
    3
    4
    5
    6
    7
    // 阴影画笔
    Paint _paintShadow = BoxShadow(
    color: Color(0x7F000000),
    blurRadius: 6.0,
    ).toPaint();
    // 绘制
    canvas.drawRect(_kRect, _paintShadow);
  • 文字的绘制

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    // 创建文字画笔
    TextPainter _textPainter = TextPainter(
    text: TextSpan(style: textStyle, text: message),
    textAlign: TextAlign.center,
    textDirection: textDirection,
    );

    // 将文字加入布局并测量
    _textPainter.layout(minWidth: width, maxWidth: width);
    // 绘制文字
    _textPainter.paint(canvas, _kRect.topLeft + Offset(0.0, (_kRect.height - _textPainter.height) / 2.0));

这里是WeninerIo😇

如果你对这次的技术分享感兴趣或者有什么疑惑🧐

不妨在评论区留言或私信🤪

或许这次的分享不是你所期待的😣

那就点个关注吧! 🙏

下次也许就是你中意的呢🫣?