Flutter Autocomplete选项列表遮挡复制粘贴工具的解决方法问询
解决Flutter Autocomplete选项列表遮挡文本复制粘贴工具的问题
针对Autocomplete选项列表遮挡系统文本操作工具栏的问题,提供以下几种实用解决方案:
方案一:调整选项列表位置,避开文本工具栏区域
通过自定义optionsViewBuilder,将选项列表移至输入框上方(而非默认的下方),从根源避免与文本工具栏重叠:
Widget _build(BuildContext context) { return BlocProvider.value( value: _autoCompleteSearchBarCubit, child: BlocBuilder<AutoCompleteSearchBarCubit, AutoCompleteSearchBarState>( builder: (context, state) { return Autocomplete<String>( optionsBuilder: (TextEditingValue textEditingValue) { return state.options; }, optionsViewBuilder: (context, onSelected, options) { // 获取输入框的位置信息,精准定位选项列表 final renderBox = context.findRenderObject() as RenderBox; final offset = renderBox.localToGlobal(Offset.zero); return Positioned( left: offset.dx, top: offset.dy - 200, // 让列表显示在输入框上方,200为列表高度 width: renderBox.size.width, child: Material( elevation: 4.0, child: SizedBox( height: 200.0, child: ListView.builder( padding: EdgeInsets.zero, itemCount: options.length, itemBuilder: (context, index) { final option = options.elementAt(index); return InkWell( onTap: () => onSelected(option), child: Padding( padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 12), child: Text(option), ), ); }, ), ), ), ); }, ); }, ), ); }
方案二:文本选中时自动隐藏选项列表
监听文本框的选中状态,当用户选中文本触发复制粘贴工具栏时,自动隐藏Autocomplete的选项列表:
final _textController = TextEditingController(); final _focusNode = FocusNode(); @override void initState() { super.initState(); // 监听文本选中变化 _textController.addListener(() { final hasSelection = _textController.selection.isValid && _textController.selection.baseOffset != _textController.selection.extentOffset; if (hasSelection) { // 有文本选中,通知Cubit清空选项 _autoCompleteSearchBarCubit.clearOptions(); } else { // 无选中,根据当前输入更新选项 _autoCompleteSearchBarCubit.updateOptions(_textController.text); } }); } @override void dispose() { _textController.dispose(); _focusNode.dispose(); super.dispose(); } Widget _build(BuildContext context) { return BlocProvider.value( value: _autoCompleteSearchBarCubit, child: BlocBuilder<AutoCompleteSearchBarCubit, AutoCompleteSearchBarState>( builder: (context, state) { return Autocomplete<String>( controller: _textController, focusNode: _focusNode, optionsBuilder: (TextEditingValue textEditingValue) { // 若有文本选中,返回空列表隐藏选项 final hasSelection = _textController.selection.isValid && _textController.selection.baseOffset != _textController.selection.extentOffset; return hasSelection ? const Iterable.empty() : state.options; }, ); }, ), ); }
注意:需要在你的AutoCompleteSearchBarCubit中实现clearOptions()和updateOptions()方法,用于控制选项列表的显示与隐藏。
方案三:降低选项列表的层级
将Autocomplete的选项列表插入到当前页面的Overlay(而非全局Root Overlay),让其层级低于系统文本工具栏:
Widget _build(BuildContext context) { return BlocProvider.value( value: _autoCompleteSearchBarCubit, child: BlocBuilder<AutoCompleteSearchBarCubit, AutoCompleteSearchBarState>( builder: (context, state) { return Autocomplete<String>( optionsBuilder: (TextEditingValue textEditingValue) { return state.options; }, optionsViewBuilder: (context, onSelected, options) { // 使用当前页面的Overlay而非全局Overlay final overlay = Overlay.of(context, rootOverlay: false); final renderBox = context.findRenderObject() as RenderBox; final offset = renderBox.localToGlobal(Offset.zero); return OverlayEntry( builder: (context) => Positioned( left: offset.dx, top: offset.dy + renderBox.size.height, width: renderBox.size.width, child: Material( elevation: 4.0, child: SizedBox( height: 200.0, child: ListView.builder( itemCount: options.length, itemBuilder: (context, index) { final option = options.elementAt(index); return ListTile( title: Text(option), onTap: () => onSelected(option), ); }, ), ), ), ), ); }, ); }, ), ); }
内容的提问来源于stack exchange,提问作者Felix A Marrero Pentón
相关产品推荐
相关产品推荐

