【问题标题】:iOS 7 TextKit - How to insert images inline with text?iOS 7 TextKit - 如何插入与文本内联的图像?
【发布时间】:2014-01-22 16:56:04
【问题描述】:

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

基本上我想在文本之间插入图像。图像只需占用 1 行空间,因此无需换行。

我尝试在子视图中添加一个 UIView:

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

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

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

【问题讨论】:

  • 一些答案​​提到使用 NSTextAttachment 和 NSTextField 上的图像属性,但我想提一下,我需要一个允许我附加 UIView 的解决方案。
  • 今天早上我刚刚通过 WWE 网络观看了 2011 年皇家大战(您的图像是从那里抓取的),我今天在这里遇到了这个问题。
  • 嘿,你有一些涉及 TextAttachment 的工作代码示例吗?

标签: ios ios7 textkit


【解决方案1】:

您可以尝试使用 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 需要一张图片。
  • @AndyHin 我自己没有对此进行测试,但一种选择可能是将您的UIView 呈现为UIImage,然后将其添加为NSTextAttachment。为了将视图呈现为图像,请查看以下问题:http://stackoverflow.com/questions/4334233/how-to-capture-uiview-to-uiimage-without-loss-of-quality-on-retina-display?lq=1
【解决方案2】:

您需要使用属性字符串并将图像添加为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];

【讨论】:

  • 我认为这是迄今为止最接近的答案。是否可以将相同的技术用于 UIView 而不是 UIImage?
  • 在 UITextView 中使用结果字符串时不显示图像
  • 如何调整 NSTextAttachment 的大小?
  • @bilobatum,我想在 textview 中添加多个图像。那么如何添加呢?
  • ` [attributedString insertAttributedString:textAttachment atIndex:4]` 优于replaceCharactersInRange
【解决方案3】:

@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)

【讨论】:

    【解决方案4】:

    扩展@bilobatum 的answer,并使用另一个问题的this category。我做了这个:

    用法:

    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] 可能为零
    【解决方案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
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2022-06-10
      • 1970-01-01
      • 2014-12-31
      • 2015-11-04
      • 1970-01-01
      • 2020-08-04
      • 1970-01-01
      • 2021-06-18
      相关资源
      最近更新 更多