iOS 7 TextKit-画像をテキストとともにインラインで挿入する方法


109

UITextViewを使用して次の効果を得ようとしています:

ここに画像の説明を入力してください

基本的に、テキストの間に画像を挿入したいと思います。画像は1行のスペースを占めるだけなので、折り返す必要はありません。

私はサブビューにUIViewを追加するだけで試しました:

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

しかし、それはテキストの上に浮かんでそれを覆っているようです。

これを実装する1つの方法であると思われる除外パスについて少し読んだ。ただし、画像を完全に配置する必要はありません。代わりに、テキストとともにフローする必要があります(<span>HTMLでの動作と同様)。


いくつかの回答では、NSTextAttachmentとNSTextFieldの画像プロパティの使用について言及していますが、UIViewを追加できるソリューションが必要であることを述べておきます。
Andy Hin

5
今朝ロイヤルランブル2011(画像が取得された場所)をWWEネットワーク経由で見たところ、驚くべきことでした。今日、この質問に遭遇しています。
bpapa 2014年

Heya、TextAttachmentを含むいくつかの動作するコードの例を持っていますか?
ファトホク2014年

回答:


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
これはこれまでのところ最も近い答えだと思います。UIImageの代わりにUIViewでこれと同じ手法を使用することは可能ですか?
Andy Hin

4
UITextViewで結果の文字列を使用する場合、これは画像を表示しません
DeepK SOreadytohelp

6
NSTextAttachmentのサイズを変更するにはどうすればよいですか?
jsetting32 14

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/

私の例では、幅に合わせて画像のサイズを変更していますが、あなたの場合は、行の高さに合わせて画像のサイズを変更したい場合があります。


これはこれまでのところ最も近い答えだと思います。UIImageの代わりにUIViewでこれと同じ手法を使用することは可能ですか?
Andy Hin

独自のカスタムクラスでいくつかの主要な作業を行うことができる場合があります。NSTextAttachmentにはデフォルトの画像属性があり、添付ファイルはNSAttributedStringの一部として保存されます。おそらく、独自のサブクラスを作成して、必要なものを何でも格納できます。表示は画像の表示に限定されているので、UIViewが役立つかどうかはわかりません。私が覚えているように、layoutManagerは画像を期待しています。
Duncan Groenewald 2014年

1
私はこれを自分でテストしていませんが、1つのオプションは、あなたをレンダリングする可能性がある@AndyHin UIViewUIImage、次にとしてそれを追加しますNSTextAttachment。ビューを画像にレンダリングするには、次の質問を確認してください
Michael Gaylord

これに関する新しい開発はありますか?
ファトホク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];、それが辞書に設定されていない場合はnilであるかもしれない:[NSFontAttributeName attributesForRange valueForKey]ので、良いはずです
ビクタークォック

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
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.