Overlay 的一种替代方案,可让您轻松地在父级边界之外渲染和命中测试小部件。
基于 @shrouxm 的原创想法:https://github.com/flutter/flutter/issues/75747

通常在 Flutter 中,如果您将小部件偏移到其父级边界之外,命中测试将会中断。DeferPointer 通过将命中测试和(可选)渲染交给树中更靠上的 DeferredPointerHandler 小部件来解决此问题。

虽然 Overlay 可以在一定程度上解决此问题,但使用 DeferPointer 具有一些优势:

  • 即插即用:无需易出错且繁琐的图层管理
  • 更细粒度:您可以将边界设置为您选择的任何祖先小部件
  • 更灵活:您可以选择在子级之上绘制,或者不绘制
  • 更容易对齐/固定到树中的某个小部件,因为这是默认的期望

这对于下拉菜单和滑动面板等大型 UI 组件以及一些小的通用样式调整非常有用。

? 安装

dependencies:
  defer_pointer: ^0.0.2

⚙ 导入

import 'package:defer_pointer/defer_pointer.dart';

?️ 用法

  1. DeferredPointerHandler 包装在您想要进行命中测试的按钮的上方某处。
  2. DeferPointer 包装在按钮本身周围。

Widget build(BuildContext context) {
    return DeferredPointerHandler(
       child: SizedBox(
           width: 100,
           height: 100,
           child: Stack(clipBehavior: Clip.none, children: [
             // Hang button off the bottom of the content
             Positioned(
               bottom: -30,
               child: DeferPointer(child: _SomeBtn(false)),
             ),
             // Content
             Positioned.fill(
               child: Container(
                 decoration: BoxDecoration(color: Colors.green, boxShadow: [
                   BoxShadow(color: Colors.black.withOpacity(1), blurRadius: 4, spreadRadius: 4),
                 ]),
               ),
             ),
           ]))));
  }

如果需要将子小部件绘制在其同级之上,请启用 paintOnTop。这将把绘制推迟到当前链接的 DeferredPointerHandler

return DeferPointer(
    paintOnTop: true,
    child: TextButton(...));

示例

此仓库中包含 4 个示例

  1. 一个将 2 个按钮偏移到其堆栈之外的简单示例
    https://github.com/gskinnerTeam/flutter-defer-pointer/blob/master/example/lib/examples/simple_offset_outside_parent.dart

  2. 经典的桌面/网页风格下拉菜单
    https://github.com/gskinnerTeam/flutter-defer-pointer/blob/master/example/lib/examples/dropdown_menus.dart

  3. 基于 Flow 小部件的动画菜单
    https://github.com/gskinnerTeam/flutter-defer-pointer/blob/master/example/lib/examples/flow_menu.dart

  4. 自动完成搜索字段
    https://github.com/gskinnerTeam/flutter-defer-pointer/blob/master/example/lib/examples/auto_complete.dart

手动链接

默认情况下,DeferPointer 小部件会使用其当前上下文查找最近的 DeferredPointerHandler。对于更复杂的用例,您可以手动分配链接来将指针绑定到处理程序

final _deferredPointerLink = DeferredPointerHandlerLink();
...
Widget build(){
    return DeferredPointerHandler(
      link: _deferredPointerLink,
      child: Padding(
          padding: const EdgeInsets.all(20),
          child: DeferPointer(
            link: _deferredPointerLink,
            child: ...,
          )),
    );
}

? Bug/请求

如果您遇到任何问题,请打开一个 issue。如果您觉得库缺少某个功能,请在 Github 上提交一个 ticket,我们将进行审查。欢迎提交 Pull Request。

? 许可证

MIT 许可

GitHub

查看 Github