Flutter RawAutocomplete无fieldViewBuilder时如何使用textEditingController
RawAutocomplete相关问题解答
不使用自定义fieldViewBuilder调用textEditingController的方法
该需求完全可以实现,不需要依赖fieldViewBuilder获取控制器,有两种可行方案:
- 优先方案:自行初始化控制器传入组件
你可以在State中提前实例化TextEditingController,构建RawAutocomplete时直接通过构造参数传入,全程持有这个实例即可随时调用,和是否自定义fieldViewBuilder没有关系。记得在组件销毁时调用dispose释放控制器避免内存泄漏。如果你不想编写任何fieldViewBuilder代码,可以直接使用RawAutocomplete的上层封装组件
Autocomplete,它内置了默认的输入框实现,同样支持传入自定义的textEditingController,不需要额外写输入框布局代码。 - 备选方案:通过上下文获取内部控制器
如果不想自己维护控制器实例,可以在RawAutocomplete的子树上下文中(比如optionsViewBuilder的构建上下文、输入框的子组件上下文中),通过RawAutocomplete.of(context).textEditingController拿到组件内部维护的控制器实例。这种方式依赖上下文层级,使用前需要做非空判断,稳定性弱于自行传入控制器的方案。
输入框从AppBar移到body区域的可行性
该需求完全可实现,RawAutocomplete本身不会对输入框的位置做任何强制约束:
- 不管是默认输入框还是自定义输入框,你可以把它放在Scaffold的任意位置:AppBar、body、底部栏、甚至悬浮组件都可以
- 选项浮层是通过
optionsViewBuilder完全自定义的,你只需要调整浮层的对齐、偏移参数,就可以让选项列表正常显示在输入框对应的位置,不会出现位置错位问题。
最简实现示例
class _AutocompleteDemoState extends State<AutocompleteDemo> { // 自行持有控制器实例 late final TextEditingController _inputController; final List<String> _options = const ['Flutter', 'Dart', 'RawAutocomplete', 'Scaffold']; @override void initState() { super.initState(); _inputController = TextEditingController(); // 可以随时直接调用控制器,不需要依赖fieldViewBuilder _inputController.addListener(() { debugPrint('当前输入内容:${_inputController.text}'); }); } @override void dispose() { _inputController.dispose(); super.dispose(); } @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar(title: const Text('Demo')), // 输入框放置在body区域 body: Padding( padding: const EdgeInsets.all(16), child: Autocomplete<String>( // 传入自定义控制器 textEditingController: _inputController, optionsBuilder: (TextEditingValue value) { if (value.text.isEmpty) return []; return _options.where((item) => item.contains(value.text)); }, // 不需要自定义fieldViewBuilder,使用默认输入框即可 optionsViewBuilder: (context, onSelected, options) { return Align( alignment: Alignment.topLeft, child: Material( elevation: 4, child: SizedBox( width: MediaQuery.of(context).size.width - 32, child: ListView.builder( shrinkWrap: true, itemCount: options.length, itemBuilder: (context, index) { final option = options.elementAt(index); return ListTile( title: Text(option), onTap: () => onSelected(option), ); }, ), ), ), ); }, ), ), ); } }
内容的提问来源于stack exchange,提问作者Viktor
相关产品推荐
相关产品推荐

