#flutter #flutter-layout #flutter-web
#flutter #flutter-макет #flutter-web
Вопрос:
Я работаю над веб-приложением Flutter, которое включает чат.
Я хотел бы включить обычную функцию ввода, в которой пользователи могут вводить текст и отправлять его в поток чата. Стандартная функция приложений для чатов в наши дни — это send
включение <ENTER>
и выполнение разрыва строки <SHIFT-ENTER>
или некоторая вариация этого.
В настоящее время я смог выполнить только одну из этих функций одновременно. Если вы установите значение TextField
‘s keyboardType
в TextInputType.multiline
значение then <ENTER>
и <SHIFT-ENTER>
всегда выполняете разрыв строки, похоже, нет способа переопределить это поведение.
Если вместо TextField
этого TextInputType.text
вы можете захватить <ENTER>
и отправить, но попытка захвата <SHIFT-ENTER>
для добавления разрыва строки не сработала. Я пытался вручную захватить нажатие клавиши с помощью onKey
обработчика и вставить n
в controller.text
, но, похоже, это TextInputType.text
вообще не предназначено для многострочного, поэтому оно не работает хорошо.
Просто интересно, сталкивались ли с этим какие-либо другие разработчики или предлагали какие-либо подходящие решения. В идеале решение также будет работать на Android / ios. Что касается меня, я решил TextInputType.text
пока отказаться от многострочной функциональности.
Спасибо
Ответ №1:
Как бы то ни было, я смог придумать разумное решение, которое я опубликую ниже на случай, если кто-нибудь столкнется с этим самостоятельно.
Я завернул текстовое поле в прослушиватель клавиатуры, который вызывает мою onSend
функцию, когда видит, что это an <Enter>
. Я пробовал это раньше, но, думаю, раньше мне не хватало приведения RawKeyEventDataWeb
, которое позволяло мне захватывать isShiftPressed
новые строки <SHFT-ENTER>
без принудительной отправки. К сожалению, мне пришлось добавить немного хакерского кода, чтобы удалить n
то, что добавляется при нажатии enter, но это небольшая цена за функциональный современный обмен сообщениями.
RawKeyboardListener(
focusNode: focusNode,
onKey: handleKeyPress,
child: TextField(
controller: messageController,
minLines: 1,
maxLines: null,
textInputAction: TextInputAction.done,
style: normalTextStyle,
keyboardType: TextInputType.multiline,
decoration: InputDecoration(
isDense: true,
hintText: 'Type a message',
hintStyle: TextStyle(
fontSize: 16,
color: Color(0xFF474749),
),
border: InputBorder.none,
),
),
)
void handleKeyPress(event) {
if (event is RawKeyUpEvent amp;amp; event.data is RawKeyEventDataWeb) {
var data = event.data as RawKeyEventDataWeb;
if (data.code == "Enter" amp;amp; !event.isShiftPressed) {
final val = messageController.value;
final messageWithoutNewLine =
messageController.text.substring(0, val.selection.start - 1)
messageController.text.substring(val.selection.start);
messageController.value = TextEditingValue(
text: messageWithoutNewLine,
selection: TextSelection.fromPosition(
TextPosition(offset: messageWithoutNewLine.length),
),
);
_onSend();
}
}
}
Ответ №2:
Этого можно добиться, добавив a FocusNode
в TextField
. Поместите узел фокусировки в состояние вашего виджета.
late final _focusNode = FocusNode(
onKey: (FocusNode node, RawKeyEvent evt) {
if (!evt.isShiftPressed amp;amp; evt.logicalKey.keyLabel == 'Enter') {
if (evt is RawKeyDownEvent) {
_sendMessage();
}
return KeyEventResult.handled;
}
else {
return KeyEventResult.ignored;
}
},
);
В вашей build
функции добавьте фокус при создании TextField
.
TextField(
autofocus: true,
controller: _textController,
focusNode: _focusNode,
)
Комментарии:
1. очень рабочий ответ без какого-либо дополнительного виджета
Ответ №3:
Лучший способ Enter
отключить клавишу для ввода и вместо этого отправить ее, когда ctrl
клавиша не нажата, — это использовать focusNode непосредственно на входе, таким образом, вам не придется удалять лишние новые строки.
class _InputTextState extends State<InputText> {
late final _focusNode = FocusNode(onKey: handleKeyPress);
@override
Widget build(BuildContext context) {
return TextField(
focusNode: _focusNode,
);
}
KeyEventResult handleKeyPress(FocusNode focusNode, RawKeyEvent event) {
// handles submit on enter
if (kIsWeb amp;amp;
event.isKeyPressed(LogicalKeyboardKey.enter) amp;amp;
!event.isControlPressed amp;amp;
!event.isShiftPressed) {
widget.onSubmit();
// handled means that the event will not propagate
return KeyEventResult.handled;
}
return KeyEventResult.ignored;
}
}