toly-popover-usage
TolyPopover 浮层组件使用规范。在需要实现弹出浮层(表情面板、右键菜单、@选择器等)时激活,确保使用正确的 API 和配置方式。
Codex または Claude でインストール この Prompt をコピーして Codex、Claude、または他のアシスタントに貼り付けると、Skill ページを確認してインストールできます。
メニュー
TolyPopover 浮层组件使用规范。在需要实现弹出浮层(表情面板、右键菜单、@选择器等)时激活,确保使用正确的 API 和配置方式。
Codex または Claude でインストール この Prompt をコピーして Codex、Claude、または他のアシスタントに貼り付けると、Skill ページを確認してインストールできます。
SOC 職業分類に基づく
GitHub Release 发布操作规范。在需要发布版本、上传安装包到 GitHub Release 时激活,确保使用正确的命令和流程。
确认/删除等交互弹框统一使用 showTolyPopPicker 底部弹出样式。在需要弹出确认框、删除确认、操作选择时激活,确保交互风格一致。
后端服务启动与数据库操作规范。在需要启动后端服务、运行 API 测试、执行数据库迁移或遇到连接错误时激活,确保使用正确的命令和流程。
功能归档规范。在归档功能版本、更新功能网、创建存档快照时激活,确保节点编号正确、网络图完整。
使用 tolyui_mediax 实现媒体预览。适用于图片九宫格展示、全屏预览、手势缩放、视频播放、Hero 动画等场景。
Flutter Widget/Page 组件代码评审技能。在需要审查组件代码质量、发现设计问题时激活,确保输出结构化的问题清单和改进建议。
| name | toly-popover-usage |
| description | TolyPopover 浮层组件使用规范。在需要实现弹出浮层(表情面板、右键菜单、@选择器等)时激活,确保使用正确的 API 和配置方式。 |
| metadata | {"model":"manual","last_modified":"Mon, 08 Jun 2026 00:00:00 GMT"} |
当需要在某个触发元素附近弹出浮层内容时使用,例如:
包名:tolyui_feedback(通过 package:tolyui_feedback/tolyui_feedback.dart 导入)
包裹触发元素的 Widget,内部管理浮层的显隐和定位。
TolyPopover(
// 浮层方位(相对于触发元素)
placement: Placement.top,
// 浮层内容(静态)
overlay: EmojiPanel(onEmojiSelected: _onSelect),
// 或:浮层内容(动态,可获取 controller)
overlayBuilder: (context, ctrl) => MyContent(onClose: ctrl.close),
// 控制器(可选,不传则内部自动创建)
controller: _popCtrl,
// 触发元素构建器(可获取 controller 来手动控制开关)
builder: (context, ctrl, child) => GestureDetector(
onTap: ctrl.open,
child: child,
),
// 子组件(builder 中的 child 参数)
child: Icon(Icons.emoji_emotions_outlined),
// 点击外部是否关闭(默认 true)
barrierDismissible: true,
// 浮层最大宽高
maxWidth: 360,
maxHeight: 300,
// 装饰配置(气泡尖角 or 普通卡片)
decorationConfig: DecorationConfig(
backgroundColor: Colors.white,
radius: Radius.circular(12),
),
// 生命周期回调
onOpen: () => debugPrint('opened'),
onClose: () => debugPrint('closed'),
)
手动控制浮层开关:
final PopoverController _ctrl = PopoverController();
// 打开浮层
_ctrl.open();
// 关闭浮层
_ctrl.close();
// 查询状态
_ctrl.isOpen;
// 通过右键位置打开(用于右键菜单)
_ctrl.open(position: details.localPosition);
浮层相对于触发元素的方位:
| 值 | 说明 |
|---|---|
Placement.top | 上方居中 |
Placement.topStart | 上方左对齐 |
Placement.topEnd | 上方右对齐 |
Placement.bottom | 下方居中 |
Placement.bottomStart | 下方左对齐 |
Placement.bottomEnd | 下方右对齐 |
Placement.left | 左侧居中 |
Placement.right | 右侧居中 |
浮层外观装饰:
// 普通卡片(圆角 + 阴影,无箭头)
DecorationConfig(
backgroundColor: Colors.white,
radius: Radius.circular(12),
isBubble: false, // 默认 true,不设会带气泡尖角!
)
// 带气泡尖角(默认行为)
DecorationConfig(
backgroundColor: Colors.white,
radius: Radius.circular(8),
// isBubble: true(默认)
bubbleMeta: BubbleMeta(spineHeight: 8, angle: 70),
)
TolyPopover(
placement: Placement.topStart,
maxWidth: 400,
maxHeight: 280,
overlay: EmojiPanel(onEmojiSelected: _onEmojiSelected),
builder: (context, ctrl, child) => GestureDetector(
onTap: () => ctrl.isOpen ? ctrl.close() : ctrl.open(),
child: child,
),
child: const Icon(Icons.emoji_emotions_outlined, size: 22),
)
final PopoverController _menuCtrl = PopoverController();
TolyPopover(
controller: _menuCtrl,
placement: Placement.bottomStart,
overlayBuilder: (context, ctrl) => _buildContextMenu(ctrl),
builder: (context, ctrl, child) => GestureDetector(
onSecondaryTapUp: (details) {
ctrl.open(position: details.localPosition);
},
child: child,
),
child: MessageBubbleContent(...),
)
final PopoverController _mentionCtrl = PopoverController();
TolyPopover(
controller: _mentionCtrl,
placement: Placement.topStart,
maxHeight: 200,
overlay: MentionPicker(
members: _members,
onSelect: (userId, nickname) {
_onMentionSelected(userId, nickname);
_mentionCtrl.close();
},
onDismiss: _mentionCtrl.close,
),
child: TextField(
controller: _textController,
onChanged: (text) {
if (_shouldShowMention(text)) {
_mentionCtrl.open();
}
},
),
)
不要用 OverlayEntry:TolyPopover 内部基于 OverlayPortal(Flutter 3.x 原生),自动管理浮层生命周期,不需要手动管理 OverlayEntry。
barrierDismissible:默认 true,点击外部自动关闭。如果浮层内有输入框(如搜索),注意 TapRegion 的分组不要冲突。
滚动自动关闭:TolyPopover 内置了 PopHideMixin,当页面滚动时会自动关闭浮层。
动画:内置淡入淡出动画(默认 250ms),通过 animDuration 和 reverseDuration 可调。
position 参数:ctrl.open(position: offset) 传入的是相对于触发元素的局部坐标,用于右键菜单场景定位。
maxWidth/maxHeight:约束浮层最大尺寸,超出时内容区域可滚动。
gap:浮层与触发元素的间距,默认根据是否有气泡尖角自动计算(有尖角时为 spineHeight + 2,无尖角时为 12)。