iOS 7 TextKit-如何在文本中插入图像?


109

我正在尝试使用UITextView获得以下效果:

在此处输入图片说明

基本上我想在文本之间插入图像。该图像仅占用一排空间,因此不需要包装。

我尝试只是将UIView添加到子视图中:

UIView *pictureView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 25, 25)];
[pictureView setBackgroundColor:[UIColor redColor]];
[self.textView addSubview:pictureView];

但是它似乎漂浮在文本上并覆盖了文本。

我对排除路径进行了一些阅读,这似乎是实现此目的的一种方法。但是,我不想绝对定位图像-相反,它应该随文本一起流动(类似于<span>HTML中的行为)。


一些答案提到使用NSTextAttachment和NSTextField上的图像属性,但是我想提到我需要一个允许我附加UIView的解决方案。
安迪·辛

5
令人惊奇的是,我今天早上刚刚通过WWE网络观看了Royal Rumble 2011(从中捕获了您的图片),而今天我正在讨论这个问题。
bpapa 2014年

嘿,您有一个涉及TextAttachment的工作代码示例吗?
fatuhoku

Answers:


180

您需要使用属性字符串,并将图像添加为的实例NSTextAttachment

NSMutableAttributedString *attributedString = [[NSMutableAttributedString alloc] initWithString:@"like after"];

NSTextAttachment *textAttachment = [[NSTextAttachment alloc] init];
textAttachment.image = [UIImage imageNamed:@"whatever.png"];

NSAttributedString *attrStringWithImage = [NSAttributedString attributedStringWithAttachment:textAttachment];

[attributedString replaceCharactersInRange:NSMakeRange(4, 1) withAttributedString:attrStringWithImage];

4
我认为这是迄今为止最接近的答案。是否可以将相同的技术用于UIView而不是UIImage?
安迪·辛

4
在UITextView中使用结果字符串时,这不会显示图像
DeepK SOreadytohelp 2014年

6
如何调整NSTextAttachment的大小?
jsetting32 2014年

2
@bilobatum,我想在textview中添加多个图像。那我该如何添加?
Diken Shah 2015年

3
`[attributedString insertAttributedString:textAttachment atIndex:4]优于replaceCharactersInRange
DawnSong

26

@bilobatum的代码已转换为需要帮助的Swift:

let attributedString = NSMutableAttributedString(string: "like after")

let textAttachment = NSTextAttachment()

textAttachment.image = UIImage(named: "whatever.png")

let attrStringWithImage = NSAttributedString(attachment: textAttachment)

attributedString.replaceCharacters(in: NSMakeRange(4, 1), with: attrStringWithImage)

20

您可以尝试使用NSAttributedString和NSTextAttachment。请看以下链接,以获取有关自定义NSTextAttachment以便调整图像大小的更多详细信息。 http://ossh.com.au/design-and-technology/software-development/implementing-rich-text-with-images-on-os-x-and-ios/

在我的示例中,我调整图像的大小以适合宽度,在您的情况下,您可能希望调整图像的大小以匹配行高。


我认为这是迄今为止最接近的答案。是否可以将相同的技术用于UIView而不是UIImage?
安迪·辛

您可能可以在自己的自定义类上进行一些主要工作。NSTextAttachment具有默认的图像属性,附件存储为NSAttributedString的一部分。您可能可以创建自己的子类并存储所需的任何内容。我认为显示仅限于显示图像,因此不确定UIView是否有用。我记得,layoutManager期望图像。
Duncan Groenewald 2014年

1
@AndyHin我自己尚未测试过,但是一个选择可能是将您呈现UIViewUIImage,然后将其添加为NSTextAttachment。为了将视图渲染为图像,请查看以下问题:http
Michael Gaylord 2014年

有什么新进展吗?
fatuhoku 2014年

5

扩展@bilobatum的答案,并在另一个问题中使用此类别。我做了这个:

用法:

UILabel *labelWithImage = [UILabel new];
labelWithImage.text = @"Tap [new-button] to make a new thing!";
NSAttributedString *stringWithImage = [labelWithImage.attributedText attributedStringByReplacingOccurancesOfString:@"[new-button]" withImage:[UIImage imageNamed:@"MyNewThingButtonImage"] scale:0];
labelWithImage.attributedText = stringWithImage;

实现方式:

@interface NSMutableAttributedString (InlineImage)

- (void)replaceCharactersInRange:(NSRange)range withInlineImage:(UIImage *)inlineImage scale:(CGFloat)inlineImageScale;

@end

@interface NSAttributedString (InlineImages)

- (NSAttributedString *)attributedStringByReplacingOccurancesOfString:(NSString *)string withInlineImage:(UIImage *)inlineImage scale:(CGFloat)inlineImageScale;

@end

@implementation NSMutableAttributedString (InlineImages)

- (void)replaceCharactersInRange:(NSRange)range withInlineImage:(UIImage *)inlineImage scale:(CGFloat)inlineImageScale {

    if (floorf(inlineImageScale) == 0)
        inlineImageScale = 1.0f;

    // Create resized, tinted image matching font size and (text) color
    UIImage *imageMatchingFont = [inlineImage imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate];
    {
        // Font size
        NSDictionary *attributesForRange = [self attributesAtIndex:range.location effectiveRange:nil];
        UIFont *fontForRange = [attributesForRange valueForKey:NSFontAttributeName];
        CGSize imageSizeMatchingFontSize = CGSizeMake(inlineImage.size.width * (fontForRange.capHeight / inlineImage.size.height), fontForRange.capHeight);

        // Some scaling for prettiness
        CGFloat defaultScale = 1.4f;
        imageSizeMatchingFontSize = CGSizeMake(imageSizeMatchingFontSize.width * defaultScale,     imageSizeMatchingFontSize.height * defaultScale);
        imageSizeMatchingFontSize = CGSizeMake(imageSizeMatchingFontSize.width * inlineImageScale, imageSizeMatchingFontSize.height * inlineImageScale);
        imageSizeMatchingFontSize = CGSizeMake(ceilf(imageSizeMatchingFontSize.width), ceilf(imageSizeMatchingFontSize.height));

        // Text color
        UIColor *textColorForRange = [attributesForRange valueForKey:NSForegroundColorAttributeName];

        // Make the matching image
        UIGraphicsBeginImageContextWithOptions(imageSizeMatchingFontSize, NO, 0.0f);
        [textColorForRange set];
        [inlineImage drawInRect:CGRectMake(0 , 0, imageSizeMatchingFontSize.width, imageSizeMatchingFontSize.height)];
        imageMatchingFont = UIGraphicsGetImageFromCurrentImageContext();
        UIGraphicsEndImageContext();
    }

    // Text attachment with image
    NSTextAttachment *textAttachment = [NSTextAttachment new];
    textAttachment.image = imageMatchingFont;
    NSAttributedString *imageString = [NSAttributedString attributedStringWithAttachment:textAttachment];

    [self replaceCharactersInRange:range withAttributedString:imageString];
}

@end

@implementation NSAttributedString (InlineImages)

- (NSAttributedString *)attributedStringByReplacingOccurancesOfString:(NSString *)string withInlineImage:(UIImage *)inlineImage scale:(CGFloat)inlineImageScale {

    NSMutableAttributedString *attributedStringWithImages = [self mutableCopy];

    [attributedStringWithImages.string enumerateOccurancesOfString:string usingBlock:^(NSRange substringRange, BOOL *stop) {
        [attributedStringWithImages replaceCharactersInRange:substringRange withInlineImage:inlineImage scale:inlineImageScale];

    }];

    return [attributedStringWithImages copy];
}

@end

将行更改 UIFont *fontForRange = [attributesForRange valueForKey:NSFontAttributeName];UIFont *fontForRange = [attributesForRange valueForKey:NSFontAttributeName] ?: [UIFont fontWithName:@"HelveticaNeue" size:12.0];应该更好,因为如果未在字典中设置[attributesForRange valueForKey:NSFontAttributeName]可能为nil
Victor Kwok

5

简单示例中的问题解决方案是 在此处输入图片说明

let attachment = NSTextAttachment()
attachment.image = UIImage(named: "qrcode")

let iconString = NSAttributedString(attachment: attachment)
let firstString = NSMutableAttributedString(string: "scan the ")
let secondString = NSAttributedString(string: "QR code received on your phone.")

firstString.append(iconString)
firstString.append(secondString)

self.textLabel.attributedText = firstString
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.