背景:前些天忽然想作一个笔记本功能,一开始,以为挺简单的呀,一个UITextView,网络缓存也不干了,直接本地NSUserDefault存储,而后完事了,美工,弄几张好看的图片,加几个动画,也就这样了。接着,按照惯例,查看已有的备忘录软件,其app store知名的软件:Weiconote等。
才发现没那么简单。这里先不考虑图文混排的问题,首先面对的就是:键盘隐藏以后,文字的位置移动问题啦。细心的体验后发现:系统的备忘录,已经一些作得好的软件,都会进行一些处理,例如:
1.当我编辑的时候,光标应该是一直不被键盘高度隐藏的才对。
2.我在文字中间进行编辑的话,编辑完成隐藏键盘,UITextView的文字位置这个时候应该是我刚才编辑的部分。
因而开始写:
1. 查看了暴露出来的API,属性,不被键盘高度遮住,frame,contentInset,textContainerInset,均可以作到。
根据键盘的自己的 notification ,或者UITextView delegate ,能轻易作到。
部分代码:
2.解决方法比较麻烦,查看了全部的api,就只有父类的这个api有用的:
- (void)scrollRectToVisible:(CGRect)rect animated:(bool)animate;
接下来的问题来了,根据光标当前的位置高度,手动计算属性,而后,获取要移动的位置,进行跳转。由于默认的状况是:只要键盘隐藏了,会自动跳到UITextView的最前面的。至于获取光标位置,以及计算移动的位置的问题,能够很快查到资料的。
事实上,问题2最好的解决方式是:本身根据TextKit封装一个UITextView...
上面的背景就是这样了,解决了问题后,发现,为何不顺便把图文混排的问题也一次性解决了。一直以来,富文本编辑都是没有深刻的,以前也是直接用的开源代码,或者UIWebView,老是内心不踏实,卡顿的状况偶尔发生,很是不开心。因而,接下来,才是今天主要想分享的东西了:富文本问题。
关键词:coretext textkit
第三方库分析:DTCoretext M80AttributedLabel FastText EGOText
官网参考资料:
TextKit能让咱们本身手动管理字体的颜色,样式(Text Layout),触摸事件,排版,图文的混排规则。
Textkit是基于CoreText的,与WebKit是两个不一样的分支。我主要查看的也是TextKit,用coreText太麻烦了。而它们之间的关系逻辑以下图所示:
具体到显示上,渲染的流程是先从存储的NSTextStorage中获取text以及它的attributes,再通过NSLayoutManager布局显示容器包括形状,大小等,再通过NSTextContainer布局呈具体的显示,最后展现在UI上。渲染和实现的流程:
这里注意描述:By using multiple text containers, each with an associated text view, more complex layout arrangements are possible.
到了这里,基本心理有个谱了。大体清楚这个逻辑了。接下来细分一下:
a.这里,先说一下具体到文本的样式,先上一张官方的说明图:
咱们能够设置文字的字体各类细节,段落排版,对其方式,缩进规则等。
关于样式:自带有六种,经过UIFont直接设置:
b.而后开始写图文混排了
参考代码:
NSMutableAttributedString *string;
经过插入NSTextAttachment设置image对象,其中NSTextAttachment能够继承重写方法实现修改插入内容大小。
这里实际上就是找到一个NSRange位置而后插入图片,常见的插入表情。而后表情转换成字符串输出出来。字符串再转换成图片输出。
咱们能够遍历输入的字符串,经过NSTextStorage设置字符串的字体,进行自定义规则处理等,例如,##进行标题大写,高亮等。
经过NSLayoutManager来设置输入文本内容行数,文本段的缩进规则,行间距等。
经过NSTextContainer来设置文字的布局方式,例如图文环绕方式,等。
基本的Text Kit 功能这样子了,基本能知足富文本的全部要求了。本身排版,按照本身项目的业务逻辑作一些事情。
最后仍是附加开头提到的一些库,阅读好的源码分析比什么都好:
M80AttributedLabel:基本的TextKit封装,代码易懂,例子很是好用简单,试过效果挺好,须要作一些性能优化处理。
DTCoretext: CoreText封装,解析正规的HTML源码,展现出来成富文本,很是强大,若是安卓端和IOS使用同一套接口的时候,就很是好用了。兼容问题。
部分参考连接:
⚠:DTCoreText 运行的时候有提示须要先进行:git submodule init update