iOS 图文混排 链接 可点击
对于这个话题 我想到
1 第一个解决方法就是使用 webView 比较经典
把所有复杂工作都交给控件本身去处理了, 但是好像好多需要自定义的地方 没法从 webView获得响应回调 :(估计也可以实现 也比较复杂,而且 这个需要对 html编码进行分析理解剥离等)
2 富文本方式 核心框架 coretext
图文混排 一点问题都没有 关键是怎么对 目标图片 或者链接 进行触发响应
要点:
(1)首先要封装的要相对独立 拓展也方便 首当其冲就是 和服务端约定的 数据模型 CoreTextModel 要敲定:
我们约定是 一段文字中间用 "[1]" 做标记 [我是图片id] ,同时传一个图片 和相应描述文字 "图片数组" 图片数组元素中主键就是这个图片id . 使用正则 去组织 CoreTextModel 数组集合
我们开发过程中是默认一张图片 点击这个图 展示解释 所以 直接知道这张图片大小 进行绘制, 如果是网络图片 那么就应该预留这张图片的大小 因为 绘制如果 不知道大小 线性绘制过程 就会卡在这 如果预知大小 那么就会继续往下绘制, 变成异步的
所以图片大小(宽高) 当然 也是这个图片数组元素 作为数据模型中的.属性元素而存在
如果是链接呢?? 所以 [1] 也可以认为是 [我是链接的id] 然后模型中有个参数 区分 当前 需要插入的是图片 还是 链接 或者其他需求 然后进行枚举判断
那么有几种枚举 就要有几个数据结构 比如这里 就有coreTextImageData && coreTextLinkData 和 绘制的过程 就需要 有几种可变数组 枚举的过程 分别进行add
(2)其次 绘制
首先来说 绘制 就是 直接动用底层CoreText
绘制图片\链接 都是动用底层 我现在的能力 是 调用\理解\修改\拓展 还不能自如的 写任意 自己想写东西 我想 也许当我到了这种程度 才能成为 大神吧 哈哈 路漫漫修远兮 吾将上下求索
1,遍历数据模型 CoreTextModel 数组 对 文本 夹杂"[1]"的重新组织
2,最终得到的富文本NSMutableAttributedString *result 都会通过 result.length 知道当前的图片/链接coreTextImageData/ coreTextLinkData的起始位置.
3,绘制 draw
a,绘制图片 (1)CTRunDelegateCallbacks callbacks;创建内存存储空间(怎么使用 百度 一大堆) (2) 使用0xFFFC作为空白的占位符 拼入 add 在result里
b,绘制链接 或者是一段连续子串 触发 给他指定颜色 下划线 大小等 同样 也add在result里
c,最终得到的 result 通过 创建CTFramesetterRef实例 获得 获得要缓制的区域的高度 再将生成好的CTFrameRef实例
ctFrame 和计算好的缓制高度height保存到CoreTextData实例中,最后返回CoreTextData实例(CoreTextData 这个结构体里面至少有ctFrame,height,result, coreTextImageData , coreTextLinkData )
ctFrame 这个 相当于 OC中 的 CGFrame , 但是成镜像且上下颠倒
盗个图:
CGFrame

Core Text CTFrameRef

所以如果触发点击事件 那么 还需要把这个绘制坐标 转成UI坐标
4,那么 现在 得到的result
在指定点击的UIView 要使用iPhone重绘机制drawRect 触发方法[self setNeedsDisplay] 调用- (void)drawRect:(CGRect)rect
就可展示出 这个视图了.
- (void)drawRect:(CGRect)rect
{
[super drawRect:rect];
if (self.data == nil) {//self.data 是 CoreTextData
return;
}
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextSetTextMatrix(context, CGAffineTransformIdentity);
CGContextTranslateCTM(context, , self.bounds.size.height);
CGContextScaleCTM(context, 1.0, -1.0);
CTFrameDraw(self.data.ctFrame, context);
//对所有指定位置的图片填充
for (CoreTextImageData * imageData in self.data.imageArray) {
UIImage *image = [UIImage imageNamed:imageData.name];
if (image) {
CGContextDrawImage(context, imageData.imagePosition, image.CGImage);
}
}
}
(4)触发点击事件
原理: 触发点击UIView 通过 UIGestureRecognizer * tapRecognizer.
点击事件中 可以获得 CGPoint point = [recognizer locationInView:self]; 点击焦点 . 那么 判断 这个 点击焦点 是不是 图 或者 是不是可触发的链接 或者字符串 就可以了
a,遍历 self.data.imageArray 判断 是否存在满足条件 如果满足 则 用 通知post 去触发点击响应

我使用了一个参数 focusRect 把焦点区域放大 一圈 防止 图片 太小点击 不上 这个是我开发过程中 需要也是必要的 大家用不用 看心情
链接 就举一反三吧 网上讲解也一大堆 目的达到了
好的链接参考
下一篇 接着讲 触发弹出 一个对话框的逻辑
iOS 图文混排 链接 可点击的更多相关文章
- Unity插件之NGUI学习(5)—— 创建Label图文混排及文字点击
创建一个新的Scene,并按 Unity插件之NGUI学习(2)创建UI Root. 准备工作,制作Font.如今Project窗体创建一个Font目录.然后从系统自带字体目录中选择自己须要的字体,我 ...
- ios图文混排
图文混排的形式 1. 富文本形式 2. core Text(文字排版) 3. TextKit 4. UIWebView 一.富文本 我们可以采用attributeString来进行图文混排.例如一个文 ...
- iOS 图文混排
使用系统自带的NSAttributedString来处理,对于一般的图文混排已经足够了,但是,有一个缺点就是NSAttributedString并不支持gif动画.实际上,使用gif动画还是挺卡的. ...
- TextView + Spanned实现图文混排以及图片点击交互
最近要实现图文混排的需求,webview过大,所以想到了用SpannableStringBuilder来实现. 不过参考了大量国内文章,大多数是教你如何实现图文混排,并没有提及图片点击交互的.有翻阅了 ...
- iOS图文混排的几种方式
最近优化升级了之前做的一个项目,现在这一期已接近尾声了,今天可以腾出些时间总结一下最近项目中用的比较多的图片文字混排显示的内容.现在遇到比较多的图文混排的基本有三种:一种是在标签中显示 价格符号+价格 ...
- [UGUI]图文混排(六):点击区域
点击区域可以分成两部分来分析: 0.Rect 搜索api:Rect和Rect.Rect,可以知道: 在GUI和GUILayout中,Rect的原点在左上角,向右为x轴正方向,向下为y轴正方向: 除此之 ...
- iOS 图文混排 (Swift版)
// 0> 图片附件 let attachment = NSTextAttachment() attachment.image = #imageLiteral(resourceName: &qu ...
- CoreText实现图文混排之文字环绕及点击算法
系列文章: CoreText实现图文混排:http://www.jianshu.com/p/6db3289fb05d CoreText实现图文混排之点击事件:http://www.jianshu.co ...
- 高性能图文混排框架,构架顺滑的iOS应用-b
About GallopGallop是一个功能强大.性能优秀的图文混排框架. Features主要用于解决以下需求: 滚动列表的性能优化.Gallop使用异步绘制.视图层级合并.观察mainRunlo ...
随机推荐
- STL学习笔记(算法概述)
算法头文件 要运用C++标准程序库的算法,首先必须包含头文件<algorithm> 使用STL算法时,经常需要用到仿函数以及函数配接器.它们定义域<functional>头文件 ...
- 【Excle】科学计数法快速还原
在Excle的单元格中,如果输入大于11位的数字,结果就会以E+形式显示 如果是单个输入的话,只需要把Excle中的单元格格式设置为文本即可,然后输入就不会出现科学计数法,但是有时候是从外部导入的序号 ...
- UUID(即GUID)
UUID(GUID)是Cocoa Touch提供的一种生成唯一标识的机制.类型为CFUUIDRef的对象可以代表UUID,UUID是基于当前时间.计数器和硬件标识(通常是以太网卡的MAC地址)等数据计 ...
- Socket协议通讯
Socket协议通讯 服务器端代码: using System; using System.Collections.Generic; using System.ComponentModel; us ...
- Selenium3.14.1+Python安装和第一个Demo
言简意赅的说下Selenium是什么 Selenium是前台测试框架,支持IE(7, 8, 9, 10, 11),Mozilla Firefox,Safari,Google Chrome等浏览器,我只 ...
- Delphi中array of const应用
Delphi的Format函数大家都用得很多,第二个参数用着确实很方便.最近在数据库开发应用中需要自己创建一个带array of const参数的函数,对于常用的类型String,Integer,Po ...
- [django] 利用多线程添加异步任务
看到django异步大家的反应应该是celery这样的消息队列组件.如今用的最多的最推荐的也是这样的方式.然而我这需求就是请求来了,运行一个小程序.可是又不能确定这个小程序啥时候运行完.响应又要及时, ...
- eclipse 创建maven web错误Cannot change version of project facet Dynamic web module to 3.1解决方案
Dynamic Web Module 选择“3.1”,java选择“1.8”,报错:Cannot change version of project facet Dynamic web module ...
- Atitit. 如何判断软件工程师 能力模型 程序员能力模型 项目经理能力模型
Atitit. 如何判断软件工程师 能力模型 程序员能力模型 项目经理能力模型 这里能力模型的标准化是对工具的使用为基本 工具(ide,语言,类库,框架,软件) 第一步 ::可使用api 类库 框架 ...
- MySQL二:数据库操作
阅读目录 一 知识储备 二 初识SQL语言 三 系统数据库 四 创建数据库 五 数据库相关操作 一 知识储备 MySQL数据库基本操作知识储备 数据库服务器:一台计算机(对内存要求比较高) 数据库管理 ...