如何在textInputAction为Done的Flutter多行TextField中换行?
解决多行TextField同时支持换行输入与Done提交的问题
针对右侧多行TextField无法换行的问题,我们可以通过调整配置,让它既能支持换行输入,又能保留Done按钮触发onSubmitted方法。
修改方案
核心调整点:
- 将
keyboardType设置为TextInputType.multiline,让虚拟键盘显示换行键,允许输入换行 - 保留
textInputAction: TextInputAction.done,让键盘显示Done按钮,点击时触发提交 - 兼容物理键盘:通过监听按键事件,区分普通Enter(换行)和组合键(提交)
修改后的代码
import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; void main() { runApp(const MyApp()); } class MyApp extends StatelessWidget { const MyApp({super.key}); @override Widget build(BuildContext context) { return MaterialApp( title: 'Flutter Demo', theme: ThemeData( primarySwatch: Colors.blue, ), home: const MyHomePage(), ); } } class MyHomePage extends StatelessWidget { const MyHomePage({super.key}); @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: const Text('Flutter TextField Multiple Lines'), ), body: const MyStatefulWidget()); } } class MyStatefulWidget extends StatefulWidget { const MyStatefulWidget({super.key}); @override State<MyStatefulWidget> createState() => _MyStatefulWidgetState(); } class _MyStatefulWidgetState extends State<MyStatefulWidget> { late TextEditingController _controllerEnter; late TextEditingController _controllerDone; @override void initState() { super.initState(); _controllerEnter = TextEditingController(); _controllerDone = TextEditingController(); } @override void dispose() { _controllerEnter.dispose(); _controllerDone.dispose(); super.dispose(); } // 处理物理键盘按键事件 void _handleKeyEvent(RawKeyEvent event) { if (event is RawKeyDownEvent) { // 物理键盘按下Ctrl+Enter时触发提交 if (event.isControlPressed && event.logicalKey == LogicalKeyboardKey.enter) { FocusScope.of(context).unfocus(); _onSubmitted(_controllerDone.text); } // 普通Enter键插入换行 else if (event.logicalKey == LogicalKeyboardKey.enter) { final text = _controllerDone.text; final selection = _controllerDone.selection; _controllerDone.text = '${text.substring(0, selection.start)}\n${text.substring(selection.end)}'; _controllerDone.selection = selection.copyWith( baseOffset: selection.start + 1, extentOffset: selection.start + 1, ); } } } void _onSubmitted(String value) { debugPrint('\n*** onSubmitted: $value ***\n'); } @override Widget build(BuildContext context) { return Center( child: Padding( padding: const EdgeInsets.all(20.0), child: Row( mainAxisAlignment: MainAxisAlignment.center, children: [ SizedBox( width: 150, child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ const Text( 'Multiline TextField Enter', style: TextStyle(fontSize: 20), ), Focus( child: TextField( style: const TextStyle(fontSize: 20), maxLines: 3, controller: _controllerEnter, onSubmitted: (String value) { // 多行默认Enter键是换行,不会触发onSubmitted debugPrint('\n*** onSubmitted: $value ***\n'); }, ), onFocusChange: (value) { if (!value) { debugPrint('\n*** onFocusChange: ${_controllerEnter.text} ***\n'); } }, ), ], ), ), const SizedBox(width: 25), SizedBox( width: 150, child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ const Text( 'Multiline TextField Done', style: TextStyle(fontSize: 20), ), // 添加RawKeyboardListener处理物理键盘 RawKeyboardListener( focusNode: FocusNode(), onKey: _handleKeyEvent, child: TextField( style: const TextStyle(fontSize: 20), maxLines: 3, // 设置为multiline类型,启用换行输入 keyboardType: TextInputType.multiline, textInputAction: TextInputAction.done, controller: _controllerDone, onSubmitted: _onSubmitted, // 可选:调整换行行为 textCapitalization: TextCapitalization.sentences, ), ), ], ), ), ], ), )); } }
关键说明
- 虚拟键盘适配:设置
keyboardType: TextInputType.multiline后,虚拟键盘会同时显示换行键和Done键,用户点击换行键即可输入换行,点击Done键触发onSubmitted。 - 物理键盘适配:通过
RawKeyboardListener监听物理键盘事件,普通Enter键插入换行,Ctrl+Enter组合键触发提交,覆盖不同输入场景。 - 原有功能保留:保留
textInputAction: TextInputAction.done,确保Done按钮的提交逻辑正常生效。
内容的提问来源于stack exchange,提问作者Jean-Pierre Schnyder
相关产品推荐
相关产品推荐

