Flutter小记-TextField遇到emoji表情时字数问题
本文最后更新于:2023年2月3日 下午
本文记录Flutter开发过程中,当TextField
输入的字符包含emoji,最大字数限制出现统计的问题及解决方案。
需求
- 限制
TextField
的最大字数 counterText
显示当前的字数- 当前字数必须小于等于最大字数
问题描述
在使用文本框组件TextField
时,已设置了最大字符数限制为MAX_LENGTH。当输入框中同时存在文字和emoji表情时,使用TextEditingController.text.length
统计的字符长度,得到的数值不对。
具体情况是每一个emoji表情,会使length长度加2,因此导致统计到当前的字数长度length,会超过MAX_LENGTH。
问题代码demo
1 |
|
解决过程
先对问题进行排查,首先设置maxLength
是达到了我们的预期的需求1和需求2的效果。只是使用TextEditingController.text.length
统计当前字数,遇到emoji表情时,得到的数据不对。
github查找issues
首先在github上找到了相关的问题描述。都是反映了类似的问题。
https://github.com/flutter/flutter/issues/55670
https://github.com/flutter/flutter/pull/55819
但是这些问题的回答,只是在解释其合理性。通过其他人的讨论中,也没有获得有帮助的信息。
查找相关博客
接着在又在dev.to上找到了一篇相关的博客文章: Flutter UTF8 TextField length limiter and char counter。这篇博客的解决办法是计算每个字符的byte长度,以此来限制输入长度。
在项目中试了后,发现其满足了他提出的需求,但并不满足我的需求。
但是这篇文章给了我们一些有用的信息。假设我们在TextField
里输入了一些文字和emoji表情包。并通过TextEditingController.text
获得了输入框内的文字text,那么它会有以下的情况:
文字类型 | text.length | utf8.encode(text).length | text.charaters.length |
---|---|---|---|
英文 | 1 | 1 | 1 |
汉字 | 1 | 3 | 1 |
emoji表情 | 2 | 2 | 1 |
由此可见,计算当前输入的字数,我们引用的不应该是text的length
,而是charaters.length
,即字符数量。
flutter.dev查找官方文档
对于以上的问题,官方文档里也找到了解释:
This formatter does not currently count Unicode grapheme clusters (i.e. characters visible to the user), it counts Unicode scalar values, which leaves out a number of useful possible characters (like many emoji and composed characters), so this will be inaccurate in the presence of those characters. If you expect to encounter these kinds of characters, be generous in the maxLength used.
该格式化程序目前不计算Unicode字符群(即对用户可见的字符),它计算Unicode标量值,这遗漏了一些有用的可能字符(如许多表情符号和组合字符),因此在这些字符出现时,这将是不准确的。如果您希望遇到这类字符,请尽量使用maxLength。
这段解释了为什么在输入框中输入包含中文和emoji表情,我们为TextField
设置了maxLength
字段,限制字数的功能能够正常生效,但使用TextEditingController.text.length
统计当前字数,会不符合预期的原因。
代码实现
找到原因后,我们对代码进行修改
1 |
|
测试效果
尽管占用的字节大小不同,emoji表情将被视作一个字符。取到的当前字数与TextField
的counterText
的字数保持一致。输入框内可输入的字数也不会超过上限。