未经作者同意禁止转载

正在做一个项目,是一个考试答题系统,其题目的题干  或者选项都是用html语言描述的,有的题目题干甚至会出现一些复杂的公式

以及上下脚标,所以只能用 直接显示html的方法 因此找到了DTCoreText

但是由于DTCoreText  中的DTAttributedTextCell  形式特别不自由  其cell上显示html的时候 会填充到整个cell

而我们需要的效果是这样的

这样就需要我们自定义DTCoreText  中的DTAttributedTextCell    在cell上加上图片 或者别的东西  同时能调整cell上显示html所占的大小     自定义DTAttributedTextCell  方法 在随笔中有记载

但是在这个界面中  cell第一行 与其他4行并不相同,  第一行 只是原生的DTAttributedTextCell  只显示题干  而下面的四行 上面要有图片等一些东西  同时其显示html的view还不能填满整个cell

很明显   第一行和下面四行 不会是一个类型的cell  这也就引出了本文的目的

在一个tableView上加载不同类型的cell(不同的 class)   但都是根据DTAttributedTextCell 改编过来的  自定义的相关方法参照

另一篇随笔  本文主要讲怎么在tableView上引用,以及怎么修改DTCoreText中的一些代码  达到兼容  并且出现上面的效果

 

 


首先贴上我们自定义的两个cell

第一个cell 的class就是DTAttributedTextCell

第二个cell 的class是MyCell   其与DTAttributedTextCell基本相同,只不过DTAttributedTextCell 中是用代码创建的

DTAttributedTextContentView 加到了cell上       MyCell是 用storyboard创建的DTAttributedTextContentView

以及  别的控件 并进行连接        (与自定义相关的内容参照  自定义DTAttributedTextContentView)


tableViewController.m 中


这里改动比较大 因为要引用两个不同的cell  所以要进行一些判断  来确定是读取,创建哪个 cell  尤其注意 不要刻意的定性某个cell

要先进行判断  再确定cell类型

 1 - (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
 2 {
 3     MyCell *myCell;
 4     DTAttributedTextCell *dtCell;
 5     if (indexPath.row==0) {
 6         dtCell=(DTAttributedTextCell *)[self tableView:tableView preparedCellForIndexPath:indexPath];
 7         //return  dtCell.attributedTextContextView.frame.size.height+10;
 8         return [dtCell requiredRowHeightInTableView:tableView]+20;
 9     }else{
10         myCell = (MyCell *)[self tableView:tableView preparedCellForIndexPath:indexPath];
11         return  myCell.attributedTextContextView.frame.size.height+10;
12     }
13
14 }
15
16 - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
17 {
18     id cell;
19     if (indexPath.row==0) {
20         cell=(DTAttributedTextCell *)[self tableView:tableView preparedCellForIndexPath:indexPath];
21
22     }else{
23        cell = (MyCell *)[self tableView:tableView preparedCellForIndexPath:indexPath];
24     }
25     return cell;
26 }

上边两个方法是tableView 调用的第一层方法  里面都用if  进行了判断  然后  再确定相应的类型 并进行下一步调用

 1 - (id)tableView:(UITableView *)tableView preparedCellForIndexPath:(NSIndexPath *)indexPath
 2 {
 3
 4     if (!cellCache)
 5     {
 6         cellCache = [[NSCache alloc] init];
 7     }
 8
 9     // workaround for iOS 5 bug
10     NSString *key = [NSString stringWithFormat:@"%d-%d", indexPath.section, indexPath.row];
11
12     id cell = [cellCache objectForKey:key];
13
14     if (!cell)
15     {
16         // reuse does not work for variable height
17         //cell = (DTAttributedTextCell *)[tableView dequeueReusableCellWithIdentifier:cellIdentifier];
18
19         if (!cell)
20         {
21            //这里面是核心代码   判断是哪个类型 再创建对应的类型
22             if (indexPath.row==0) {
23                 cell = [[DTAttributedTextCell alloc] initWithReuseIdentifier:@"title" accessoryType:UITableViewCellAccessoryDisclosureIndicator];
24
25             }else{
26                 cell=[myTableView dequeueReusableCellWithIdentifier:@"answer"];
27             }
28
29
30         }
31
32         // cache it
33         [cellCache setObject:cell forKey:key];
34     }
35
36     [self configureCell:cell forIndexPath:indexPath];
37
38     return cell;
39 }

核心代码已经标出  同样要判断 要用哪个类型的cell  再创建对应的类型    注意 此方法 返回的参数为ID  因为我们不确定返回哪个类型的cell

 1 - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
 2     return 5;
 3 }
 4
 5 - (void)configureCell:(id)cell forIndexPath:(NSIndexPath *)indexPath
 6 {
 7     MyCell *myCell;
 8     DTAttributedTextCell *dtCell;
 9     if (indexPath.row==0) {
10         dtCell=(DTAttributedTextCell *)cell;
11         NSString *html=@"摘要: 其实说是DTAttributedTextCell解析并显示html 应该是cell上的DTAttributedTextContentView解析并显示html首先先说一下DTAttributedTextCell 解析显示html的优点a.能够很好的实现cell的自适应高度,用webView也能实现自适应高度,但是逻辑复杂,效率不高,有加";
12        //下面一句是代码的作用后面会解释
13         dtCell.attributedTextContextView.identifier=@"title";
14         [dtCell setHTMLString:html];
15         dtCell.userInteractionEnabled=NO;
16         [dtCell setSelectionStyle:UITableViewCellSelectionStyleNone];
17         dtCell.attributedTextContextView.shouldDrawImages = YES;
18         dtCell.attributedTextContextView.backgroundColor=[UIColor clearColor];
19
20     }
21     else
22     {
23         myCell=(MyCell *)cell;
24         NSString *html=@"V<sub>1</sub>+V<sub>2</sub>=V<sub>13</sub>";
25        //下面代码的作用后面会解释
26         myCell.attributedTextContextView.identifier=@"answer";
27         CGSize size=myCell.attributedTextContextView.frame.size;
28         myCell.attributedTextContextView.realSize=size;
29         [myCell setHTMLString:html];
30        myCell.ABCDlabel.text=@"A";
31         myCell.imageView.image=[UIImage imageNamed:@"answer-notselected"];
32         myCell.attributedTextContextView.backgroundColor=[UIColor clearColor];
33         myCell.attributedTextContextView.shouldDrawImages = YES;
34
35     }
36 }

这里同样进行判断来进行不同的初始化   加注释的代码有很重要的作用,  后面会详细解释

这时  cell引用没有问题  点击运行   如下图所示

第一个cell正常显示   MyCell 虽然在storyboard中我们并没有将 DTAttributedTextContentView设置为整个cell但是

运行后 仍然变为整个 cell

参考随笔(自定义DTAttributedTextCell)  我们知道    我们必须要修改一下DTAttributedTextContentView的relayoutText方法

 

DTAttributedTextContentView.h

 1 @interface DTAttributedTextContentView : UIView
 2
 3 {
 4
 5 NSAttributedString *_attributedString;
 6
 7 DTCoreTextLayoutFrame *_layoutFrame;
 8
 9
10
11 UIEdgeInsets edgeInsets;
12
13
14
15 NSMutableDictionary *customViewsForAttachmentsIndex;
16
17 //这是我们自己给其添加的一个属性,用来区分不同的实例
18 NSString *identifier;
19 //这个用来装载不同实例的 frame.size
20 CGSize realSize;
21
22 }
23
24 @property(nonatomic,retain)NSString *identifier;
25
26 @property(nonatomic)CGSize realSize;

我们自己定义了 两个实例

NSString *identifier;

CGSize realSize;

这就对应上了 我们在tableViewController.m中的

- (void)configureCell:(id)cell forIndexPath:(NSIndexPath *)indexPath

方法中的几句代码

1          myCell.attributedTextContextView.identifier=@"answer";
2          CGSize size=myCell.attributedTextContextView.frame.size;
3          myCell.attributedTextContextView.realSize=size;
4          [myCell setHTMLString:html];

在这里 我们判断出了到底使用哪个cell   然后 设定attributedTextContextView.identifier为某个特定的标记

并且将attributedTextContextView.frame.size的值传入attributedTextContextView.realSize

注意  对attributedTextContextView.identifier以及attributedTextContextView.frame.size的赋值一定要在

[myCell setHTMLString:html];  方法之前   因为这个方法调用后 才会层层深入调用  一直调用到DTAttributedTextContentView.m 中的relayoutText方法  然后我们再读取identifier  以及realsize

若放到[myCell setHTMLString:html];  之后赋值   进入relayoutText后  identifier   realSize为空   根本无法判断

DTAttributedTextContentView.m

 1 - (void)relayoutText
 2 {
 3     //CGRect frame=self.frame;
 4
 5     //下面的代码进行判断  并利用isMyCell设定了一个标志
 6     int isMyCell;
 7     if ([self.identifier isEqualToString:@"answer"]) {
 8         isMyCell=2;
 9     }else if(self.identifier==nil)
10     {
11         isMyCell=3;
12
13     }
14     else if([self.identifier isEqualToString:@"title"])
15     {
16         isMyCell=1;
17     }
18
19     // Make sure we actually have a superview before attempting to relayout the text.
20     if (self.superview) {
21         // need new layouter
22         self.layouter = nil;
23         self.layoutFrame = nil;
24         // remove all links because they might have merged or split
25        [self removeAllCustomViewsForLinks];
26
27         if (_attributedString)
28         {
29             // triggers new layout
30
31             CGSize neededSize;
32            //这里根据isMyCell的值确定 是用的哪个cell再设定一些尺寸相关的代码
33             if (isMyCell==2) {
34                 neededSize = [self sizeThatFits:self.realSize];
35                 self.frame = CGRectMake(152, self.frame.origin.y, neededSize.width, neededSize.height);
36             }
37             else if(isMyCell==1){
38                 neededSize=[self sizeThatFits:self.bounds.size];
39                 super.frame = CGRectMake(self.frame.origin.x, self.frame.origin.y, neededSize.width, neededSize.height);
40             }
41             // set frame to fit text preserving origin
42             // call super to avoid endless loop
43             [self willChangeValueForKey:@"frame"];
44
45             [self didChangeValueForKey:@"frame"];
46         }
47         [self setNeedsDisplay];
48         [self setNeedsLayout];
49     }
50 }

这段代码首先 我们根据我们事先设置好的identifier 确定了是哪个cell上的view   然后进行不同的尺寸设置

注意  这里不能直接把 if(isMyCell)换成 if([identifier isEqualtoString:@"xxx"])判断  这样会造成程序僵死   原因尚不明确

关于if()中对尺寸的设置 可以参考随笔 (自定义DTAttributedTextContentView.m

对本例的扩展:


如果我们tableView中存在更多的 cell类型  这里  可以根据这个思路,    再增加一组  identifier 并且  设置相应的尺寸

然后给isMyCell  增加编号   当然tableViewController中的判断  也要多加一个if判断  等等

 

转载于:https://www.cnblogs.com/bucengyongyou/archive/2012/09/04/2670509.html

原在一个tableView上应用不同类型的DTAttributedTextCell相关推荐

  1. Protobuf3 + Netty4: 在socket上传输多种类型的protobuf数据

    Protobuf序列化的字节流数据是不能自描述的,当我们通过socket把数据发送到Client时,Client必须知道发送的是什么类型的数据,才能正确的反序列化它.这严重影响限制了C/S功能的实现, ...

  2. Google Doc API研究之一:模拟页面上传任意类型文件

    一直以来想要做个程序,将google doc用作网盘,程序做 的差不多了才发现不是所有的人都可以上传任意类型的文件,只有商业用户才可以.商业用户是要交钱的的,这与我们倡导的免费精神相关太远.怎么办,我 ...

  3. php限制文件类型,限制上传文件类型程序代码_PHP教程

    我们一般不会在前段限制用户上传文件时的文件类,因为也没什么好的办法来限制只能使用像php,asp这类来操作,下面我来介绍利用js来定义type=file浏览上传时的文件类型与php中限制上传文件类型代 ...

  4. 服务器修改mime类型,服务器上设置mime类型

    服务器上设置mime类型 内容精选 换一换 资源包括静态语音,TTS放音以及短消息,在您进行流程编排前,需要先将涉及到的资源,包括语音.短信模板添加到系统中,才能继续配置流程. 开发过程中,您有任何问 ...

  5. html鼠标悬停出现新元素,CSS:我如何将鼠标悬停在一个元素上,并显示另一个元素?...

    我有一个导航面板,当您将鼠标悬停在灯具 上时,它会显示从主导航面板下拉的面板中的前5个灯具.CSS:我如何将鼠标悬停在一个元素上,并显示另一个元素? 我试图实现这个使用CSS与:hover. 这是:h ...

  6. SAP PM 初级系列之27 – SAP系统怎么知道某种类型的维修工单检验批上的检验类型是14?

    SAP PM 初级系列之27 – SAP系统怎么知道某种类型的维修工单检验批上的检验类型是14? 比如在SAP系统中,Calibration类型的维修工单,工单下达后自动触发了检验批,检验类型是14. ...

  7. Linux系统上的文件类型

    Linux系统上的文件类型 -: 常规文件 d: directory,目录文件 b: block device,块设备文件,支持以"block"为单位进行随机访问 c: chara ...

  8. 【MATLAB】基本绘图 ( 绘制多图 | 设置图形对话框在 Windows 界面的位置和大小 | 在一个图形上绘制多个小图形 )

    文章目录 一.绘制多图 1.绘制多图 2.代码示例 二.设置图形对话框在 Windows 界面的位置和大小 三.在一个图形上绘制多个小图形 一.绘制多图 1.绘制多图 存在一种绘图情况 , 需要同时展 ...

  9. 用ASP.net判断上传文件类型的三种方法

    一. 安全性比较低,把文本文件1.txt改成1.jpg照样可以上传,但其实现方法容易理解,实现也简单,所以网上很多还是采取这种方法. Boolean fileOk = false;           ...

  10. [ASP.NET] 限制上传文件类型的两种方法(转)

    通常,为了防止因用户上传有害文件(如木马.黑客程序)引发的安全性问题,Web程序都会对用户允许上传的文件类型加以限制.而本文将要介绍的就是如何在ASP.NET应用程序中利用Web Control的内置 ...

最新文章

  1. mysql 应用前景_图数据库在企业应用中前景如何,相比关系型数据库有哪些优势?...
  2. acwing算法题--看图做题
  3. Plenty Of Tricks to Get Irradiance Caching Practical
  4. Linux安装minikube命令整理
  5. c#通过app.manifest使程序以管理员身份运行
  6. $2019$ 暑期刷题记录 $2$(基本算法专题)
  7. 将serversocket 写在按钮事件中连接不上_Java服务器的模型—TCP连接/流量优化
  8. rust tpa_Rust(腐蚀)怎么tp求大神指教。请写在下面
  9. React Native windows环境安装遇到的坑
  10. 变换例题_小学语文学习攻略9:句式变换知识点概述+例题讲练
  11. Android 实现计时器功能,Android实现倒计时30分钟功能
  12. Android项目实战(十):自定义倒计时的TextView
  13. 《算法》第四版入门准备
  14. SWF游戏软件逆向基础知识1
  15. 2011年度全球移民国家移民条件浅析
  16. C语言编程>第二十七周 ③ 请补充fun函数,该函数的功能是计算并输出下列多项式的值:
  17. 屏幕正中间浮窗html,HTML 纯css浮窗居中和打开or关闭
  18. 广州微创软件科技有限公司面试总结
  19. 海尔集团张瑞敏经典语录
  20. Simulink 水轮机初始化设置

热门文章

  1. 全国最优秀的计算机学校,2020全国最好的计算机专业学校排名
  2. html双击单元格修改,JS实现鼠标双击选中表格单元格代码
  3. 单片机与嵌入式的关系,单片机是嵌入式的子类
  4. Java常用JSON库FastJson,Gson,Jackson,Json-lib性能及特点比较,常用工具方法
  5. 【5分钟 Paper】Continuous Control With Deep Reinforcement Learning
  6. 【5分钟 Paper】Reinforcement Learning with Deep Energy-Based Policies
  7. SSOR-PCG FORTRAN版CSR压缩存储
  8. Python-20-异常处理
  9. Mac如何彻底卸载Mysql
  10. 一个神奇的???whatever~~