Mat*_*att 13 objective-c ios autolayout ios8
我的应用程序从API中提取HTML,将其转换为NSAttributedString(为了允许可点击的链接)并将其写入AutoLayout表中的一行.麻烦的是,每当我调用这种类型的单元格时,高度都会被错误计算并且内容会被切断.我尝试过不同的行高计算实现,但都没有正常工作.
如何准确,动态地计算其中一行的高度,同时仍保持点击HTML链接的能力?
我的代码如下.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
switch(indexPath.section) {
...
case kContent:
{
FlexibleTextViewTableViewCell* cell = (FlexibleTextViewTableViewCell*)[TableFactory getCellForIdentifier:@"content" cellClass:FlexibleTextViewTableViewCell.class forTable:tableView withStyle:UITableViewCellStyleDefault];
[self configureContentCellForIndexPath:cell atIndexPath:indexPath];
[cell.contentView setNeedsLayout];
[cell.contentView layoutIfNeeded];
cell.selectionStyle = UITableViewCellSelectionStyleNone;
cell.desc.font = [UIFont fontWithName:[StringFactory defaultFontType] size:14.0f];
return cell;
}
...
default:
return nil;
}
}
Run Code Online (Sandbox Code Playgroud)
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
UIFont *contentFont = [UIFont fontWithName:[StringFactory defaultFontType] size:14.0f];
switch(indexPath.section) {
...
case kContent:
return [self textViewHeightForAttributedText:[self convertHTMLtoAttributedString:myHTMLString] andFont:contentFont andWidth:self.tappableCell.width];
break;
...
default:
return 0.0f;
}
}
Run Code Online (Sandbox Code Playgroud)
-(NSAttributedString*) convertHTMLtoAttributedString: (NSString *) html {
return [[NSAttributedString alloc] initWithData:[html dataUsingEncoding:NSUTF8StringEncoding]
options:@{NSDocumentTypeDocumentAttribute: NSHTMLTextDocumentType,
NSCharacterEncodingDocumentAttribute: @(NSUTF8StringEncoding)}
documentAttributes:nil
error:nil];
}
Run Code Online (Sandbox Code Playgroud)
- (CGFloat)textViewHeightForAttributedText:(NSAttributedString*)text andFont:(UIFont *)font andWidth:(CGFloat)width {
NSMutableAttributedString *mutableText = [[NSMutableAttributedString alloc] initWithAttributedString:text];
[mutableText addAttribute:NSFontAttributeName value:font range:NSMakeRange(0, text.length)];
UITextView *calculationView = [[UITextView alloc] init];
[calculationView setAttributedText:mutableText];
CGSize size = [self text:mutableText.string sizeWithFont:font constrainedToSize:CGSizeMake(width,FLT_MAX)];
CGSize sizeThatFits = [calculationView sizeThatFits:CGSizeMake(width, FLT_MAX)];
return sizeThatFits.height;
}
Run Code Online (Sandbox Code Playgroud)
在我正在开发的应用程序中,应用程序从其他人编写的糟糕API中提取可怕的HTML字符串,并将HTML字符串转换为NSAttributedString对象.我别无选择,只能使用这个糟糕的API.很伤心.任何必须解析可怕的HTML字符串的人都知道我的痛苦.我用Text Kit.方法如下:
NSAttributedString对象,使用自定义属性标记链接,用于NSTextAttachment标记图像.我称之为富文本.Text Kit对象.即NSLayoutManager,NSTextStorage,NSTextContainer.分配后将它们连接起来.NSTextStorage对象[NSTextStorage setAttributedString:][NSLayoutManager ensureLayoutForTextContainer:]强制布局发生[NSLayoutManager usedRectForTextContainer:].如果需要,添加填充或边距.[tableView: heightForRowAtIndexPath:][NSLayoutManager drawGlyphsForGlyphRange:atPoint:].我在这里使用离屏绘图技术,因此结果是一个UIImage对象.UIImageView来渲染最终结果图像.或者,结果图像对象传递给contents财产layer的财产contentView的财产UITableViewCell在对象[tableView:cellForRowAtIndexPath:].[NSLayoutManager glyphIndexForPoint:inTextContainer:fractionOfDistanceThroughGlyph]和[NSAttributedString attribute:atIndex:effectiveRange:].事件处理代码段:
CGPoint location = [tap locationInView:self.tableView];
// tap is a tap gesture recognizer
NSIndexPath *indexPath = [self.tableView indexPathForRowAtPoint:location];
if (!indexPath) {
return;
}
CustomDataModel *post = [self getPostWithIndexPath:indexPath];
// CustomDataModel is a subclass of NSObject class.
UITableViewCell *cell = [self.tableView cellForRowAtIndexPath:indexPath];
location = [tap locationInView:cell.contentView];
// the rich text is drawn into a bitmap context and rendered with
// cell.contentView.layer.contents
// The `Text Kit` objects can be accessed with the model object.
NSUInteger index = [post.layoutManager
glyphIndexForPoint:location
inTextContainer:post.textContainer
fractionOfDistanceThroughGlyph:NULL];
CustomLinkAttribute *link = [post.content.richText
attribute:CustomLinkAttributeName
atIndex:index
effectiveRange:NULL];
// CustomLinkAttributeName is a string constant defined in other file
// CustomLinkAttribute is a subclass of NSObject class. The instance of
// this class contains information of a link
if (link) {
// handle tap on link
}
// same technique can be used to handle tap on image
Run Code Online (Sandbox Code Playgroud)
与[NSAttributedString initWithData:options:documentAttributes:error:]渲染相同的html字符串相比,此方法更快,更可定制.即使没有剖析我也可以说Text Kit方法更快.即使我必须自己解析html并构造属性字符串,它也非常快速且令人满意.这种NSDocumentTypeDocumentAttribute方法太慢,因此是不可接受的.有了Text Kit,我还可以创建复杂的布局,如带有可变缩进,边框,任意深度嵌套文本块等的文本块.但它确实需要编写更多代码来构造NSAttributedString和控制布局过程.我不知道如何计算用它创建的属性字符串的边界矩形NSDocumentTypeDocumentAttribute.我相信创建的属性字符串NSDocumentTypeDocumentAttribute是由Web Kit而不是Text Kit.因此,不适用于可变高度表视图单元.
编辑:
如果你必须使用NSDocumentTypeDocumentAttribute,我认为你必须弄清楚布局过程是如何发生的.也许您可以设置一些断点来查看哪个对象负责布局过程.然后,也许您可以查询该对象或使用另一种方法来模拟布局过程以获取布局信息.有些人使用ad-hoc单元格或UITextView对象来计算高度,我认为这不是一个好的解决方案.因为这样,应用程序必须至少两次布局相同的文本块.无论你是否知道,在你的应用程序的某个地方,某些对象必须布置文本,这样你才能获得布局信息,如边界矩形.既然您提到了NSAttributedString类,那么最好的解决方案是Text Kit在iOS 7之后.或者Core Text如果您的应用程序是针对早期的iOS版本.
我强烈建议,Text Kit因为这样,对于从API中提取的每个html字符串,布局过程只发生一次,并且布局信息(如边界矩形和每个字形的位置)都被NSLayoutManager对象缓存.只要Text Kit保留了对象,就可以随时重用它们.当使用表视图呈现任意长度的文本时,这非常有效,因为文本只布置一次并在每次需要显示单元格时绘制.我也推荐使用Text Kit不UITextView作为官方苹果文档建议.因为UITextView如果他想重用Text Kit附加的对象,就必须缓存每一个UITextView.Text Kit像我一样将对象附加到模型对象,只更新NSTextStorage和强制NSLayoutManager从API中提取新的html字符串时的布局.如果表视图的行数是固定的,则还可以使用固定的占位符模型对象列表来避免重复分配和配置.而且因为drawRect:会导致Core Animation产生无用的支持位图必须避免,不要使用UIView和drawRect:.使用CALayer绘图技术或将文本绘制到位图上下文中.我使用后一种方法,因为这可以在后台线程中完成GCD,因此主线程可以自由响应用户的操作.我的应用程序中的结果非常令人满意,速度很快,排版很好,表格视图的滚动非常流畅(60 fps),因为所有绘图过程都是在后台线程中完成的GCD.每个应用程序都需要使用表视图绘制一些文本Text Kit.
您需要更新内在内容大小。
我假设您在此代码中将属性文本设置为标签 [self configureContentCellForIndexPath:cell atIndexPath:indexPath];
所以,它应该是这样的
cell.youLabel.attributedText = NSAttributedString(...)
cell.youLabel.invalidateIntrinsicContentSize()
cell.youLabel.layoutIfNeeded()
Run Code Online (Sandbox Code Playgroud)
您的高度计算代码(CGFloat)textViewHeightForAttributedText:(NSAttributedString*)text andFont:(UIFont *)font andWidth:(CGFloat)width 应替换为使用原型单元格的单元格高度计算。
| 归档时间: |
|
| 查看次数: |
6861 次 |
| 最近记录: |