我正在通过TextKit构建杂志应用程序,这是TextKit demo(请查看developer分支)。它从rtfd文件中加载NSAttributeString作为文本存储对象,所有页面的大小与自定义NSTextContainer对象相同,分页功能就完成了。
当我尝试将图像添加到源rtfd文件时,图像附件直接显示在UITextView中,而无需任何其他代码,太好了!但是,默认情况下,某些大图像会在文本视图框架中被裁剪。我尝试了各种委托方法和重写方法来调整其大小和重新布局,但最终都失败了。
- (void)setAttachmentSize:(CGSize)attachmentSize forGlyphRange:(NSRange)glyphRange
- (CGSize)attachmentSizeForGlyphAtIndex:(NSUInteger)glyphIndex;
setter方法在字形布局过程中调用,后者的getter方法在字形绘制过程中从调用堆栈中调用。
- (BOOL)layoutManager:(NSLayoutManager *)layoutManager shouldSetLineFragmentRect:(inout CGRect *)lineFragmentRect lineFragmentUsedRect:(inout CGRect *)lineFragmentUsedRect baselineOffset:(inout CGFloat *)baselineOffset inTextContainer:(NSTextContainer *)textContainer forGlyphRange:(NSRange)glyphRange
{
NSTextAttachment *attachment = ...;
NSUInteger characterIndex = [layoutManager characterIndexForGlyphAtIndex:glyphRange.location];
UIImage *image = [attachment imageForBounds:*lineFragmentRect textContainer:textContainer characterIndex:characterIndex];
CGSize imageSize = GetScaledToFitSize(image.size, self.textContainerSize);
CGFloat ratio = imageSize.width / imageSize.height;
CGRect rect = *lineFragmentRect, usedRect = *lineFragmentUsedRect;
CGFloat dy = *baselineOffset - imageSize.height;
if (dy > 0) {
*baselineOffset -= dy;
usedRect.size.height -= dy;
usedRect.size.width = ratio * usedRect.size.height;
}
if (!CGRectContainsRect(usedRect, rect)) {
if (rect.size.height > usedRect.size.height) {
*baselineOffset -= rect.size.height - usedRect.size.height;
rect.size.height = usedRect.size.height;
rect.size.width = ratio * usedRect.size.height;
}
if (rect.size.width > usedRect.size.width) {
//...
}
}
*lineFragmentRect = rect;
*lineFragmentUsedRect = usedRect;
return YES;
}
此委托方法可以调整布局大小,但不会影响最终的宽度和图像比例。我没有运气就尝试过serval解决方案。似乎关于SO和Apple示例代码上的TextKit上的图像的线程并不多。
请帮助,非常感谢!
最佳答案
我曾经为图像附件自动调整大小做过类似的工作。获得属性字符串后如何处理它。
也就是说,用NSAttachmentAttributeName枚举原始字符串,将附件替换为NSTextAttachment的子类,并暗示NSTextAttachmentContainer协议。
- (CGRect)attachmentBoundsForTextContainer:(nullable NSTextContainer *)textContainer proposedLineFragment:(CGRect)lineFrag glyphPosition:(CGPoint)position characterIndex:(NSUInteger)charIndex {
CGFloat lineWidth = CGRectGetWidth(lineFrag);
CGSize size = self.bounds.size;
size.height *= (size.width > 0) ? (lineWidth / size.width) : 0;
size.width = lineWidth;
return CGRectMake(0, 0, size.width, size.height);
}
上面的代码调整附件大小以适合宽度,您无需调整图像大小,因为在绘制时会自动将其调整为边界大小。
希望对您有所帮助。