Reputation: 4199
I have a text field in flutter and an emoji picker button. On selecting an emoji I need to insert it at the current cursor position.
How can I achieve this?
Currently using TextEditingController
I'm only able to append the emoji. I'm not able to get the current cursor offset.
emojiPicker() {
return EmojiPicker(
rows: 3,
columns: 7,
recommendKeywords: null,
indicatorColor: flujoAccentColor,
onEmojiSelected: (emoji, category) {
print(emoji);
_messageInputController.text =
_messageInputController.text + emoji.emoji;
}
);
}
Upvotes: 10
Views: 9239
Reputation: 329
TextSelection selection = _controller.selection;
String text = _controller.text;
//textInside to get the selected text if you want to do something with is
String selectedText = selection.textInside(text);
_controller.text ='${text.substring(0, selection.start)}$insert${text.substring(selection.end, text.length)}';
Upvotes: 0
Reputation: 1
If you want to replace the selection of text field with a new string, I found the method below is useful.
void replaceTextSelectionWith(TextEditingController textEditingController, Function(String selection) getReplaceString)
{
final text = textEditingController.text;
final selection = textEditingController.selection;
final replaceText = getReplaceString(selection.textInside(text)) as String;
final newText = text.replaceRange(selection.start, selection.end, replaceText);
textEditingController.value =
TextEditingValue(text: newText, selection: TextSelection.collapsed(offset: selection.start + replaceText.length));
}
And use it like this
replaceTextSelectionWith(textEditingController, (selection) => '**$selection**');
Upvotes: 0
Reputation: 512326
This is a slight modification to CrazyLazyCat's answer.
void _insertText(String inserted) {
final text = _controller.text;
final selection = _controller.selection;
final newText = text.replaceRange(selection.start, selection.end, inserted);
_controller.value = TextEditingValue(
text: newText,
selection: TextSelection.collapsed(offset: selection.baseOffset + inserted.length),
);
}
Notes:
_controller
is a TextEditingController
.TextEditingValue
rather than changing them individually (since they each trigger an update).TextSelection.collapsed
with the adjusted index.Upvotes: 9
Reputation: 1573
i have another solution beside text.replaceRange
.
All you need is :
TextEditingController _tec;
String youWillAddtoTEC = "your emoji or your clipboard data or else";
String beforeCursorPositionAtTEC = tec.selection.textBefore(tec.text);
String afterCursorPositionAtTEC = tec.selection.textAfter(tec.text);
String result = beforeCursorPositionAtTEC + youWillAddtoTEC + afterCursorPositionAtTEC;
and then add result to tec, or any widget your need:
tec.text = result;
for the selection or cursor position is same with above, but if you need place cursor after the "youWillAddToTEC" you can do like this:
tec.selection = TextSelection.collapsed(offset: tec.selection.start + youWillAddtoTEC.lenght);
Upvotes: 1
Reputation: 15073
_txtController.selection
to get the selection (or cursor position).import 'package:emoji_picker/emoji_picker.dart';
import 'package:flutter/material.dart';
void main() {
runApp(MaterialApp(home: HomePage()));
}
class HomePage extends StatefulWidget {
@override
_HomePageState createState() => _HomePageState();
}
class _HomePageState extends State<HomePage> {
TextEditingController _messageInputController;
@override
void initState() {
_messageInputController = TextEditingController();
super.initState();
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("Demo"),
),
body: SafeArea(
child: Column(
children: <Widget>[
EmojiPicker(
rows: 3,
columns: 7,
recommendKeywords: null,
indicatorColor: Colors.red,
onEmojiSelected: (emoji, category) {
String text = _messageInputController.text;
TextSelection textSelection = _messageInputController.selection;
String newText = text.replaceRange(
textSelection.start, textSelection.end, emoji.emoji);
final emojiLength = emoji.emoji.length;
_messageInputController.text = newText;
_messageInputController.selection = textSelection.copyWith(
baseOffset: textSelection.start + emojiLength,
extentOffset: textSelection.start + emojiLength,
);
},
),
TextField(
controller: _messageInputController,
),
],
),
),
);
}
}
with this you can not only insert the selected emoji at cursor position, but also can replace some selected text
Upvotes: 23