由于项目需要对一个label里不同的文字点击响应不同的事件,在网上也没有找到比较好的demo,只好自己动手写一个,不到之处欢迎提出
本项目是给label添加分类方法,做到引用后项目里所有UILabel都能使用
具体实现代码
CTFramesetterRef frameSetter = CTFramesetterCreateWithAttributedString((__bridge CFAttributedStringRef)self.attributedText);
// 创建path
CGMutablePathRef path = CGPathCreateMutable();
CGPathAddRect(path, NULL, self.bounds);
// 绘制frame range:传长度为0也可以。如果是0,会一直增加行数,直到text最后或者没有空间才停止。(numberOfLines)
CTFrameRef frame = CTFramesetterCreateFrame(frameSetter, CFRangeMake(0, 0), path, NULL);
// 获得CTLine数组
CFArrayRef lines = CTFrameGetLines(frame);
NSInteger numberOfLines =CFArrayGetCount(lines);
CGPoint lineOrigins[numberOfLines];
// 获取每一行的origin range同上所述(numberOfLines)
CTFrameGetLineOrigins(frame, CFRangeMake(0, 0), lineOrigins);
for (CFIndex lineIndex = 0; lineIndex < numberOfLines; lineIndex++) {
// 获取行对应的origin
CGPoint lineOrigin = lineOrigins[lineIndex];
CTLineRef line = CFArrayGetValueAtIndex(lines, lineIndex);
// 获取每行的 rect
CGFloat ascent, descent, leading, width;
width = CTLineGetTypographicBounds(line, &ascent, &descent, &leading);
// 获取富文本的行间距,默认0
NSParagraphStyle *style = [self.attributedText attribute:NSParagraphStyleAttributeName atIndex:0 effectiveRange:nil];
CGFloat lineSpace = 0;
if (style) {
lineSpace = style.lineSpacing;
}
CGFloat lineH = ascent + fabs(descent) + leading;// 行高
CGFloat textH = lineH * numberOfLines + lineSpace * (numberOfLines - 1);// 文本总高度
CGFloat textY = (self.bounds.size.height - textH) * 0.5;// 文本开始的 y
CGFloat lineY = textY + lineIndex * (lineH + lineSpace);// 当前行的开始 y
CGFloat yMax = lineH + lineY; // 当前行最大 y
if (point.y > yMax) {
continue; // 点击的位置不在该行文本中
}
if (point.y >= lineY) {
if (point.x >= lineOrigin.x && point.x <= lineOrigin.x + width) {
// 相对位置
CGPoint relativePoint = CGPointMake(point.x - lineOrigin.x, point.y - lineOrigin.y);
// 获取当前点击的文本位置
NSUInteger idx = CTLineGetStringIndexForPosition(line, relativePoint);
idx--; // 文本起始位置1 range起始位置0
[self.actionBlockDict enumerateKeysAndObjectsUsingBlock:^(AttributeActionBlock actionBlock, LWAttributeActionModel *model, BOOL * _Nonnull stop) {
if (NSLocationInRange(idx, model.range)) {
actionBlock(model.string);
}
}];
}
}
}
注意事项
- label.userInteractionEnabled = YES
- label.attributeText必须设置字体大小
网友评论