内容简介:最近有客户Alex提出Flutter输入框需要支持支持图片和特殊文字样式,就跟QQ,微信,微博一样,可以插入表情,@xxx或者一个话题. 每天追更,每天都在群里@我(FlutterCandies QQ群:181398081),就差点就把他禁言了。但是我没有这样做,客户就是上帝,因为之前做过Extended Text,假装感觉应该很简单,悄悄在空闲的时候就动手做起来了。本篇只介绍下用法,下一篇再讲讲开发中的辛酸历程,先上效果图。
extended_text_field 相关文章
- Flutter 支持图片以及特殊文字的输入框(一)使用方法
- Flutter 支持图片以及特殊文字的输入框(二)实现过程
最近有客户Alex提出Flutter输入框需要支持支持图片和特殊文字样式,就跟QQ,微信,微博一样,可以插入表情,@xxx或者一个话题. 每天追更,每天都在群里@我(FlutterCandies QQ群:181398081),就差点就把他禁言了。但是我没有这样做,客户就是上帝,因为之前做过Extended Text,假装感觉应该很简单,悄悄在空闲的时候就动手做起来了。
本篇只介绍下用法,下一篇再讲讲开发中的辛酸历程,先上效果图。
使用步骤
-
关注,点赞,转发,送飞机
-
使用ExtendedTextField
-
Flutter Candies全家桶
关注,点赞,转发,送飞机
pub 搜索 extended_text_field
github 地址: extended_text_field
定义自己的特殊文字
比如表情
我这里定义的格式是比如[1],就代表是表情1(就是你对应的表情图片).
class EmojiText extends SpecialText { static const String flag = "["; final int start; EmojiText(TextStyle textStyle, {this.start}) : super(EmojiText.flag, "]", textStyle); @override TextSpan finishText() { // TODO: implement finishText var key = toString(); if (EmojiUitl.instance.emojiMap.containsKey(key)) { //fontsize id define image height //size = 30.0/26.0 * fontSize final double size = 20.0; ///fontSize 26 and text height =30.0 //final double fontSize = 26.0; return ImageSpan(AssetImage(EmojiUitl.instance.emojiMap[key]), actualText: key, imageWidth: size, imageHeight: size, start: start, deleteAll: true, fit: BoxFit.fill, margin: EdgeInsets.only(left: 2.0, top: 2.0, right: 2.0)); } return TextSpan(text: toString(), style: textStyle); } } class EmojiUitl { final Map<String, String> _emojiMap = new Map<String, String>(); Map<String, String> get emojiMap => _emojiMap; final String _emojiFilePath = "assets"; static EmojiUitl _instance; static EmojiUitl get instance { if (_instance == null) _instance = new EmojiUitl._(); return _instance; } EmojiUitl._() { for (int i = 1; i < 49; i++) { _emojiMap["[$i]"] = "$_emojiFilePath/$i.png"; } } } 复制代码
再举一个
比如 @法的空间
以@为开始标志,空格为结束标志
class AtText extends SpecialText { static const String flag = "@"; final int start; /// whether show background for @somebody final bool showAtBackground; final BuilderType type; AtText(TextStyle textStyle, SpecialTextGestureTapCallback onTap, {this.showAtBackground: false, this.type, this.start}) : super(flag, " ", textStyle, onTap: onTap); @override TextSpan finishText() { // TODO: implement finishText TextStyle textStyle = this.textStyle?.copyWith(color: Colors.blue, fontSize: 16.0); final String atText = toString(); if (type == BuilderType.extendedText) return TextSpan( text: atText, style: textStyle, recognizer: TapGestureRecognizer() ..onTap = () { if (onTap != null) onTap(atText); }); return showAtBackground ? BackgroundTextSpan( background: Paint()..color = Colors.blue.withOpacity(0.15), text: atText, actualText: atText, start: start, deleteAll: false, style: textStyle, recognizer: type == BuilderType.extendedText ? (TapGestureRecognizer() ..onTap = () { if (onTap != null) onTap(atText); }) : null) : SpecialTextSpan( text: atText, actualText: atText, start: start, deleteAll: false, style: textStyle, recognizer: type == BuilderType.extendedText ? (TapGestureRecognizer() ..onTap = () { if (onTap != null) onTap(atText); }) : null); } } 复制代码
定义文字解析帮助类
必须实现createSpecialText方法,这样才知道你有哪些特殊文字
一个是build的方法,可选实现。如果你自己实现了要注意,特殊TextSpan必须放在返回的TextSpan的children里面,我只会遍历这一层,不会再去查找children的children了。
class MySpecialTextSpanBuilder extends SpecialTextSpanBuilder { /// whether show background for @somebody final bool showAtBackground; final BuilderType type; MySpecialTextSpanBuilder( {this.showAtBackground: false, this.type: BuilderType.extendedText}); @override TextSpan build(String data, {TextStyle textStyle, onTap}) { // TODO: implement build var textSpan = super.build(data, textStyle: textStyle, onTap: onTap); //for performance, make sure your all SpecialTextSpan are only in textSpan.children //extended_text_field will only check SpecialTextSpan in textSpan.children return textSpan; } @override SpecialText createSpecialText(String flag, {TextStyle textStyle, SpecialTextGestureTapCallback onTap, int index}) { if (flag == null || flag == "") return null; // TODO: implement createSpecialText ///index is end index of start flag, so text start index should be index-(flag.length-1) if (isStart(flag, AtText.flag)) { return AtText(textStyle, onTap, start: index - (AtText.flag.length - 1), showAtBackground: showAtBackground, type: type); } else if (isStart(flag, EmojiText.flag)) { return EmojiText(textStyle, start: index - (EmojiText.flag.length - 1)); } else if (isStart(flag, DollarText.flag)) { return DollarText(textStyle, onTap, start: index - (DollarText.flag.length - 1), type: type); } return null; } } enum BuilderType { extendedText, extendedTextField } 复制代码
使用ExtendedTextField
是不是炒鸡简单,这样你的文字就会自动转换为对应的特殊文字类型了
ExtendedTextField( specialTextSpanBuilder: MySpecialTextSpanBuilder( showAtBackground: true, type: BuilderType.extendedTextField), 复制代码
限制
跟 readme 上面讲的一样,有三种限制。
- 不支持文字从右到左,也就是不支持TextDirection.rtl。原因是TextPainter 给的图片的位置,非常奇怪,完全没法搞。当然我会继续跟进,也许哪天官方修好了呢?
- 不支持那种密码的输入样式解析成特殊TextSpan,也就是不支持obscureText 为true。没啥好解释,文字都变成******了,也没必要解析了。
- 代码是基于flutter 版本1.5.7,可能在不同的flutter 版本下面会出现编译错误,如果出现,希望老板们能根据自己的版本进行更正。我这边不太可能都适配到每个flutter 版本,我会尽量让 extended_text_field 在flutter 的稳定版本上面没有错误,希望谅解。
最后放上 extended_text_field ,如果你有什么不明白或者对这个方案有什么改进的地方,请告诉我,欢迎加入 Flutter Candies ,一起生产可爱的Flutter 小糖果(QQ群:181398081)
Flutter Candies全家桶
最最后放上 Flutter Candies 全家桶,真香。
custom flutter candies(widgets) for you to easily build flutter app, enjoy it.
以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网
猜你喜欢:- canvas压缩图片以及卡片制作
- Flutter 支持图片以及特殊文字的输入框(二)实现过程
- 网页图片等比例缩小实现方案总结以及最佳实践
- 详解Apache配置图片防盗链以及隐藏版本信息
- itchat 保存好友信息以及生成好友头像图片墙
- 图片上传姿势以及你不知道的 Typed Arrays
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
算法概论
Sanjoy Dasgupta、Christos Papadimitriou、Umesh Vazirani / 王沛、唐扬斌、刘齐军 / 清华大学出版社 / 2008-7 / 39.99元
《国外经典教材·算法概论》涵盖了绝大多数算法设计中的常用技术。在表达每一种技术时,阐述它的应用背景,强调每个算法运转背后的简洁数学思想,注意运用与其他技术类比的方法来说明它的特征,并提供了大量相应实际问题的例子。《国外经典教材·算法概论》同时也注重了对每一种算法的复杂性分析。全书共10章,从基本的数字算法人手,先后介绍了分治、图的遍历、贪心算法、动态规划、线性规划等技术,对NP完全问题进行厂基本而......一起来看看 《算法概论》 这本书的介绍吧!