Flutter Text Selection Controls弃用,如何用contextMenuBuilder实现自定义选中文本工具栏?
Flutter 中MaterialTextSelectionControls已被标记为弃用,官方推荐使用contextMenuBuilder来实现自定义文本选择菜单。以下是替代原有方案,在选中文本的默认工具栏旁添加「打开地图」按钮的完整实现:
核心实现逻辑
- 给
SelectableRegion设置contextMenuBuilder参数,替代原有的selectionControls - 复用默认文本选择菜单项,插入自定义的「打开地图」按钮
- 处理自定义按钮点击逻辑,获取选中文本并触发地图打开操作
完整代码示例
SelectableRegion( contextMenuBuilder: (context, selectableRegionState) { // 获取当前选中的文本内容 final selectedText = selectableRegionState.selectedText ?? ''; return AdaptiveTextSelectionToolbar( anchors: selectableRegionState.contextMenuAnchors, children: [ // 保留默认的复制/剪切/粘贴/全选功能按钮 if (selectableRegionState.canCopy) TextSelectionToolbarTextButton( onPressed: () { selectableRegionState.copySelection(SelectionChangedCause.toolbar); selectableRegionState.hideContextMenu(); }, child: const Text('复制'), ), if (selectableRegionState.canCut) TextSelectionToolbarTextButton( onPressed: () { selectableRegionState.cutSelection(SelectionChangedCause.toolbar); selectableRegionState.hideContextMenu(); }, child: const Text('剪切'), ), if (selectableRegionState.canPaste) TextSelectionToolbarTextButton( onPressed: () async { await selectableRegionState.pasteText(SelectionChangedCause.toolbar); selectableRegionState.hideContextMenu(); }, child: const Text('粘贴'), ), if (selectableRegionState.canSelectAll) TextSelectionToolbarTextButton( onPressed: () { selectableRegionState.selectAll(SelectionChangedCause.toolbar); selectableRegionState.hideContextMenu(); }, child: const Text('全选'), ), // 添加自定义「打开地图」按钮 if (selectedText.isNotEmpty) TextSelectionToolbarTextButton( onPressed: () { // 调用你的地图打开逻辑 openLink(generateLocationLinkFromQuery(selectedText)); selectableRegionState.hideContextMenu(); }, child: const Text('打开地图'), ), ], ); }, focusNode: _selectableRegionFocusNode, // 保留原有其他参数 child: const Text('这里是可选中的文本内容,比如地址:北京市朝阳区'), )
关键细节说明
- 选中文本获取:通过
selectableRegionState.selectedText直接获取选中内容,无需旧方案中的delegate - 默认菜单复用:利用
selectableRegionState提供的canCopy、canCut等状态判断,保留原有功能 - 菜单位置适配:使用
selectableRegionState.contextMenuAnchors确保菜单显示位置与默认行为一致 - 菜单关闭逻辑:点击按钮后调用
selectableRegionState.hideContextMenu(),替代旧方案的delegate.hideToolbar()
如果需要贴合Material设计风格,也可以基于MaterialTextSelectionContextMenu实现,减少重复代码:
contextMenuBuilder: (context, selectableRegionState) { final selectedText = selectableRegionState.selectedText ?? ''; return MaterialTextSelectionContextMenu( selectableRegionState: selectableRegionState, children: [ // 复用Material默认的文本选择按钮 ...MaterialTextSelectionContextMenu.buttonItems( context: context, selectableRegionState: selectableRegionState, ).map((item) => TextSelectionToolbarTextButton( onPressed: item.onPressed, child: Text(item.label), )), // 插入自定义按钮 if (selectedText.isNotEmpty) TextSelectionToolbarTextButton( onPressed: () { openLink(generateLocationLinkFromQuery(selectedText)); selectableRegionState.hideContextMenu(); }, child: const Text('打开地图'), ), ], ); },
内容的提问来源于stack exchange,提问作者user123
相关产品推荐
相关产品推荐

