在Flutter中创建日语假名可编辑文本

问题描述

我想创建一个romaji转假名转换器EditableText。也就是说,通过在EditableText中写“ saikou”,显示的文本应该例如是“さいこう”。

当前,如果用户继续写而不希望编辑他的内容,那么我就可以正常工作 文本(但由于错误的偏移,光标位于文本的开头而不是结尾)。

但是,一旦用户手动移动TextSelection(通过点击EditableText上的某个位置),光标便最终定位正确,但是当他尝试编辑文本(添加删除字符)时,错误的偏移会导致混乱

示例:

用户想要删除“こ”。他将光标移到此处(由竖线表示):“さいこ|う”。但是当他按Delete键时,“い”字符将消失。这是因为原始文本(saikou)和日语翻译(“さいこう”)的长度不同。原始文本长度为6,但日语长度仅为4。通过将光标放置在这样的位置并按“删除键”,我们将尝试删除原始文本中字母为“ i”的第三个字符,而不是日语翻译中的“こ”。

想法

我可以编写一个将原始偏移量与相应的日语偏移量相匹配的函数。但这仅在我可以防止发生认文本删除并以编程方式更新文本的情况下才有用。但是,我找不到防止删除方法。 我已经尝试过在EditableText上使用onChange方法,但是尽管尝试返回该函数,但仍会发生修改。我还研究了EditableText的Controller并尝试在触发侦听器时更改文本,但是由于此侦听器状态的改变,它导致了无限循环。

任何帮助将不胜感激!

First letter

First kana

解决方法

在没有看到任何代码的情况下进行注释有点棘手,但让我们看看。

因此,我用Javascript设置了此解决方案,然后将其移植到Flutter。希望这会有所帮助。无论输入开始时光标是否在末尾,这对我都有效。

final newText = convertFromRomaji(oldText);
final origPosition = tController.selection.start;
final origLength = oldText.length;
final newLength = newText.length;
final newPosition = newLength - (origLength - origPosition);

tController.value = tController.value.copyWith(
text: newText,selection : TextSelection(baseOffset : newPosition,extentOffset: newPosition)
);

前四行只是分配,第1行使用您拥有的所有内容从romaji转换为平假名。 tController附加到TextField。这是TextField:

TextField(
    controller: tController,onChanged: (text) => setText(text) /* calls the above code */
); 

这不会像日本IME一样保留原始罗马字。进行转换后,旧的罗马字将被丢弃,只有日本人保留。

我没有您描述的问题,所以这是?解决问题的方法。