我正在通过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);
}


上面的代码调整附件大小以适合宽度,您无需调整图像大小,因为在绘制时会自动将其调整为边界大小。

希望对您有所帮助。

09-30 16:36
查看更多