Overlay/OverlayEntry - 声明式而非命令式,直观的上下文,以及简易的对齐想要显示浮动覆盖层 - 工具提示、上下文菜单、对话框、气泡等?这个库是对 Flutter 内置 Overlay/OverlayEntry 的增强和替代。
为什么使用 flutter_portal 而不是内置的 Overlay/OverlayEntry/OverlayPortal?
.insert() 等方式进行命令式操作。</sub>shiftToWithinBound),将其与 portal 而不是父 widget 对齐(alignToPortal),您甚至可以创建自己的对齐算法(扩展 EnhancedCompositedTransformAnchor)。<sub>对比:Overlay 似乎没有这种功能。</sub>Context:覆盖层条目使用其直观的父级作为 context 进行构建。<sub>对比:Overlay 方法使用远处的覆盖层作为其 context。更新:OverlayPortal(受本包启发)在这方面有所改进。</sub>因此,还具有以下优点:
setState 一样简单,RestorableProperty 可以很好地工作。<sub>对比:使用 Overlay 方法时,当应用程序被操作系统终止时,我们的模态框状态不会被恢复。</sub>Theme/provider:由于覆盖层条目具有直观的 context,它可以访问与显示覆盖层的 widget 相同的 Theme 和不同的 provider。<sub>对比:Overlay 方法会产生令人困惑的 Theme 和 provider。更新:OverlayPortal(受本包启发)在这方面有所改进。</sub>PortalTarget( // 1. 声明式:只需将 `portalFollower` 作为普通 widget 提供 // 2. 内部具有直观的 BuildContext portalFollower: MyAwesomeOverlayWidget(), // 3. 可以随意将"follower"相对于"child"对齐 anchor: Aligned.center, child: MyChildWidget(), )
要从 0.x 迁移到 1.x,请参阅 readme 的最后一节。
查看 examples 文件夹以了解如何使用 flutter_portal 的示例:
部分截图:
| 上下文菜单 | 引导视图 |
|---|---|
| <img width="300px" src="https://yellow-cdn.veclightyear.com/835a84d5/01194457-be4f-4ee2-aa68-a47fd0dc6cad.png"> | <img src="https://yellow-cdn.veclightyear.com/835a84d5/49c56226-c731-4092-b81f-19f5d48d85af.gif" alt="Discovery example" style="300px"> |
flutter pub add flutter_portal。MaterialApp 之上。每个应用程序只需要一个 Portal。在这个例子中,我们将看到如何使用 flutter_portal 在点击 RaisedButton 后显示菜单。
在做任何事情之前,您必须在 widget 树中插入 Portal widget。follower widget 将表现得好像它们是作为这个 widget 的子项插入的。
您可以将这个 Portal 放在 MaterialApp 之上或靠近路由的根部:
Portal( child: MaterialApp(...) )
首先,我们需要创建一个渲染 RaisedButton 的 StatefulWidget:
<p align="center"> <img src="https://yellow-cdn.veclightyear.com/835a84d5/3519d458-852b-4660-887b-ce6168abb246.png" alt="image" width="200px"> </p>class MenuExample extends StatefulWidget { _MenuExampleState createState() => _MenuExampleState(); } class _MenuExampleState extends State<MenuExample> { Widget build(BuildContext context) { return Scaffold( body: Center( child: RaisedButton( onPressed: () {}, child: Text('show menu'), ), ), ); } }
然后,我们需要在 widget 树中插入 PortalTarget。
我们希望上下文菜单紧靠 RaisedButton 渲染。
因此,我们的 PortalTarget 应该是 RaisedButton 的父级,如下所示:
child: PortalTarget( visible: // TODO anchor: // TODO portalFollower: // TODO child: RaisedButton(...), ),
我们可以将菜单传递给 PortalTarget:
<p align="center"> <img width="200px" src="https://yellow-cdn.veclightyear.com/835a84d5/8c1938bb-bb97-4dca-a192-30a49822b198.png"> </p>PortalTarget( visible: true, anchor: Filled(), portalFollower: Material( elevation: 8, child: IntrinsicWidth( child: Column( mainAxisSize: MainAxisSize.min, children: [ ListTile(title: Text('option 1')), ListTile(title: Text('option 2')), ], ), ), ), child: RaisedButton(...), )
在这个阶段,您可能会注意到两件事:
anchor 是 Filled)visible 是 true)让我们先解决全屏问题,并更改我们的代码,使菜单在 RaisedButton 的右侧渲染。
要将菜单对齐到按钮周围,我们可以更改 anchor 参数:
<p align="center"> <img width="200px" src="https://yellow-cdn.veclightyear.com/835a84d5/09125d1b-b7b3-4291-a818-6778db9088dc.png"> </p> 这段代码的意思是,将菜单的左上角与 `RaisedButton` 的右上角对齐。这样,我们的菜单就不再是全屏的,而是位于按钮的右侧。PortalTarget( visible: true, anchor: const Aligned( follower: Alignment.topLeft, target: Alignment.topRight, ), portalFollower: Material(...), child: RaisedButton(...), )
最后,我们可以更新代码,使菜单只在点击按钮时显示。
为此,我们需要在 StatefulWidget 中声明一个新的布尔值,表示菜单是否打开:
class _MenuExampleState extends State<MenuExample> { bool isMenuOpen = false; ... }
然后,我们将这个 isMenuOpen 变量传递给 PortalEntry:
PortalTarget( visible: isMenuOpen, ... )
接着,在 RaisedButton 的 onPressed 回调中,我们可以更新这个 isMenuOpen 变量:
RaisedButton( onPressed: () { setState(() { isMenuOpen = true; }); }, child: Text('show menu'), ),
最后一步是在用户点击菜单外部时关闭菜单。
这可以通过结合使用第二个 PortalEntry 和 [GestureDetector] 来实现,如下所示:
PortalTarget( visible: isMenuOpen, portalFollower: GestureDetector( behavior: HitTestBehavior.opaque, onTap: () { setState(() { isMenuOpen = false; }); }, ), ... ),
在使用flutter_portal时,有几个概念需要充分理解。特别是如果你想支持自定义用例,这在提供的抽象API中是很容易实现的。
以下将高层次地解释你需要理解的每个抽象概念。你会在类名(如Portal部件或PortalTarget部件)以及参数名中找到它们。
Portal(或者如果你只有一个的话,就是the portal)是用于进行所有portal工作的空间。在底层,这意味着你有一个部件,允许其子树放置相互连接的目标和跟随者。
Portal还定义了可供任何跟随者在屏幕上渲染的可用区域(矩形边界)。
具体来说,你可能会将整个MaterialApp包裹在一个单独的Portal部件中,这意味着你可以使用应用的整个区域来渲染附加到Portal部件子级的目标的跟随者。
目标是portal内可以被跟随者跟随的任何位置。这允许你将任何你想要叠加的内容附加到UI中的特定位置,无论它如何动态移动。
在底层,这意味着你将UI中你想要跟随的部分包裹在一个PortalTarget部件中并进行配置。
想象你想在应用中当头像被悬停时显示工具提示。在这种情况下,头像将是portal的目标,可用于锚定叠加的工具提示。
另一个例子是下拉菜 单。显示当前选择的部件是目标,当点击它时,下拉选项将通过portal作为跟随者叠加显示。
跟随者只能与目标结合使用。你可以将其用于任何你想要叠加在UI顶部的内容,附加到目标上。
具体来说,这意味着你可以为每个PortalTarget传递一个follower,当你指定时,它将显示在UI上方的portal内。
如果你想使用flutter_portal显示一个自动完成文本字段,你会想要跟随文本字段来叠加你的自动完成建议。在这种情况下,自动完成建议的部件将是portal的跟随者。
锚点定义了目标和跟随者之间的布局连接。通常,锚点被实现为一个抽象API,提供支持任何你想要的定位所需的所有信息。这意味着锚点可以基于相关portal、目标和跟随者的属性来定义。
默认实现了一些锚点,例如Aligned或Filled。
从0.x到1.0版本有一些破坏性变更(主要由#44引入),但可以轻松迁移。以下是示例:
PortalEntry( portalAnchor: Alignment.topLeft, childAnchor: Alignment.topRight, portal: MyAwesomePortalWidget(), child: MyAwesomeChildWidget(), )
变为:
PortalTarget( anchor: const Aligned( follower: Alignment.topLeft, target: Alignment.topRight, ), portalFollower: MyAwesomePortalWidget(), child: MyAwesomeChildWidget(), )
如果你原本使用PortalEntry时没有设置portalAnchor/childAnchor(即使其全屏显示),那么你可以这样写:
PortalTarget( anchor: const Filled(), ... )
所有者
CHANGELOG.md了解贡献。贡献者


免费创建高清无水印Sora视频
Vora是一个免费创建高清无水印Sora视频的AI工具


最适合小白的AI自动化工作流平台
无需编码,轻松生成可复用、可变现的AI自动化工作流

大模型驱动的Excel数据处理工具
基于大模型交互的表格处理系统,允许用户通过对话方式完成数据整理和可视化分析。系统采用机器学习算法解析用户指令,自动执行排序、公式计算和数据透视等操作,支持多种文件格式导入导出。数据处理响应速度保持在0.8秒以内,支持超过100万行数据的即时分析。


AI辅助编程,代码自动修复
Trae是一种自适应的集成开发环境(IDE),通过自动化和多元协作改变开发流程。利用Trae,团队能够更快速、精确地编写和部署代码,从而提高编程效率和项目交付速度。Trae具备上下文感知和代码自动完成功能,是提升开发效率的理想工具。


AI论文写作指导平台
AIWritePaper论文写作是一站式AI论文写作辅助工具,简化了选题、文献检索至论文撰写的整个过程。通过简单设定,平台可快速生成高质量论文大纲和全文,配合图表、参考文献等一应俱全,同时提供开题报告和答辩PPT等增值服务,保障数据安全,有效提升写作效率和论文质量。


AI一键生成PPT,就用博思AIPPT!
博思AIPPT,新一代的AI生成PPT平台,支持智能生成PPT、AI美化PPT、文本&链接生成PPT、导入Word/PDF/Markdown文档生成PPT等,内置海量精美PPT模板,涵盖商务、教育、科技等不同风格,同时针对每个页面提供多种版式,一键自适应切换,完美适配各种办公场景。


AI赋能电商视觉革命,一站式智能商拍平台
潮际好麦深耕服装行业,是国内AI试衣效果最好的软件。使用先进AIGC能力为电商卖家批量提供优质的、低成本的商拍图。合作品牌有Shein、Lazada、安踏、百丽等65个国内外头部品牌,以及国内10万+淘宝、天猫、京东等主流平台的品牌商家,为卖家节省将近85%的出图成本,提升约3倍出图效率,让品牌能够快速上架。


企业专属的AI法律顾问
iTerms是法大大集团旗下法律子品牌,基于最先进的大语言模型(LLM)、专业的法律知识库和强大的智能体架构,帮助企业扫清合规障碍,筑牢风控防线,成为您企业专属的AI法律顾问。


稳定高效的流量提升解决方案,助力品牌曝光
稳定高效的流量提升解决方案,助力品牌曝光


最新版Sora2模型免费使用,一键生成无水印视频
最新版Sora2模型免费使用,一键生成无水印视频
最新AI工具、AI资讯
独家AI资源、AI项目落地

微信扫一扫关注公众号