• Flutter如何实现新手指引功能?
  • 发布于 2个月前
  • 755 热度
    0 评论
  • DuXing
  • 7 粉丝 50 篇博客
  •   
当我们上线一个新功能时经常需要做个气泡引导用户使用,但如何在不改变布局的情况下给Widget加上气泡呢? 我们可以通过OverlayEntry在更高的页面层级上插入气泡,同时根据相对的Widget位置来计算气泡的位置,具体代码实现如下。 需要注意的是,虽然我们在Widget的dispose中会销毁气泡,但如果Widget是页面并且页面有弹窗,气泡会出现在弹窗上,所以使用的时候需要在弹窗前主动销毁气泡。
// 堆代码 duidaima.com
// 以相对widget为中心扩展刚好容纳bubble大小的Rect
Rect _expandRelativeRect(BuildContext relativeContext, Size bubbleSize, bool allowOutsideScreen) {
  if ((relativeContext as Element)?.isElementActive != true) {
    return Rect.zero;
  }

  // 找到相对widget的位置和大小
  final RenderBox renderBox = relativeContext.findRenderObject();
  final Offset offset = renderBox.localToGlobal(Offset.zero);
  final Size size = renderBox.size;
  // 以相对widget为中心扩展刚好容纳bubble大小的Rect
  final rect = Rect.fromLTWH(offset.dx - bubbleSize.width, offset.dy - bubbleSize.height,
                             bubbleSize.width * 2 + size.width, bubbleSize.height * 2 + size.height);
  if (allowOutsideScreen) {
    return rect;
  } else {
    final screenSize = MediaQueryData.fromWindow(ui.window).size;
    final screenRect = Rect.fromLTWH(0, 0, screenSize.width, screenSize.height);
    return rect.intersect(screenRect);
  }
}
/// 构建气泡Entry
OverlayEntry bubbleEntry = OverlayEntry(builder: (bubbleContext) {
  Rect rect = _expandRelativeRect(relativeContext, bubbleSize, allowOutsideScreen);
  return Positioned.fromRect(
      rect: rect,
      child: Align(
          alignment: alignment,
          child: SizedBox(
            child: bubble.call(bubbleContext),
            width: bubbleSize.width,
            height: bubbleSize.height,
          )));
});
Overlay.of(context).insert(bubbleEntry);

/// 关闭气泡
VoidCallback hideBubbleCallback = () {
  if (!bubbleEntry.mounted) {
    return;
  }
  bubbleEntry.remove();
};

用户评论