iOS 7 TextKit - Bagaimana cara memasukkan gambar sejajar dengan teks?

109

Saya mencoba untuk mendapatkan efek berikut menggunakan UITextView:

masukkan deskripsi gambar di sini

Pada dasarnya saya ingin menyisipkan gambar di antara teks. Gambar hanya dapat menempati 1 baris ruang sehingga tidak perlu pembungkusan.

Saya mencoba menambahkan UIView ke subview:

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

Tapi sepertinya itu mengapung di atas teks dan menutupinya.

Saya membaca sedikit di jalur pengecualian yang tampaknya menjadi salah satu cara untuk menerapkan ini. Namun, saya tidak ingin benar-benar memposisikan gambar - sebaliknya, itu harus mengalir dengan teks (mirip dengan bagaimana <span>berperilaku dalam HTML).

Andy Hin
sumber
Beberapa jawaban menyebutkan menggunakan properti gambar pada NSTextAttachment dan NSTextField tetapi saya ingin menyebutkan bahwa saya memerlukan solusi yang memungkinkan saya untuk menambahkan UIView.
Andy Hin
5
Luar biasa bahwa saya baru saja menonton Royal Rumble 2011 pagi ini (di mana gambar Anda diambil) melalui jaringan WWE dan di sini saya membahas pertanyaan ini hari ini.
bpapa
Heya, apakah Anda punya contoh beberapa kode kerja yang melibatkan TextAttachment?
fatuhoku

Jawaban:

180

Anda harus menggunakan string yang diatribusikan dan menambahkan gambar sebagai contoh 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];
bilobatum
sumber
4
Saya pikir ini adalah jawaban yang paling mendekati sejauh ini. Apakah mungkin untuk menggunakan teknik yang sama ini dengan UIView daripada UIImage?
Andy Hin
4
Ini tidak menampilkan gambar saat menggunakan string yang dihasilkan di UITextView
DeepK SOreadytohelp
6
Bagaimana cara mengubah ukuran NSTextAttachment?
jsetting32
2
@bilobatum, saya ingin menambahkan lebih dari satu gambar ke textview. Jadi bagaimana saya bisa menambahkan?
Diken Shah
3
`[atributedString insertAttributedString: textAttachment atIndex: 4]` lebih baik daripadareplaceCharactersInRange
DawnSong
26

Kode @ bilobatum diubah menjadi Swift bagi yang membutuhkan:

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)
Justin Vallely
sumber
20

Anda dapat mencoba menggunakan NSAttributedString dan NSTextAttachment. Lihatlah tautan berikut untuk detail lebih lanjut tentang menyesuaikan NSTextAttachment untuk mengubah ukuran gambar. http://ossh.com.au/design-and-technology/software-development/implementing-rich-text-with-images-on-os-x-and-ios/

Dalam contoh saya, saya mengubah ukuran gambar agar sesuai dengan lebarnya, dalam kasus Anda, Anda mungkin ingin mengubah ukuran gambar agar sesuai dengan tinggi garis.

Duncan Groenewald
sumber
Saya pikir ini adalah jawaban yang paling mendekati sejauh ini. Apakah mungkin untuk menggunakan teknik yang sama ini dengan UIView daripada UIImage?
Andy Hin
Anda mungkin dapat mengerjakan beberapa pekerjaan besar pada kelas kustom Anda sendiri. NSTextAttachment memiliki atribut gambar default dan lampiran disimpan sebagai bagian dari NSAttributedString. Anda mungkin dapat membuat subkelas Anda sendiri dan menyimpan apa pun yang Anda inginkan. Saya pikir tampilan terbatas untuk menampilkan gambar jadi tidak yakin UIView akan berguna. Seingat saya layoutManager mengharapkan sebuah gambar.
Duncan Groenewald
1
@AndyHin Saya belum menguji ini sendiri, tetapi satu opsi mungkin untuk membuat Anda UIViewmenjadi UIImagedan kemudian menambahkannya sebagai NSTextAttachment. Untuk merender tampilan menjadi gambar, periksa pertanyaan ini: http://stackoverflow.com/questions/4334233/how-to-capture-uiview-to-uiimage-without-loss-of-quality-on-retina- tampilan? lq = 1
Michael Gaylord
Ada perkembangan baru dengan ini?
fatuhoku
5

Memperluas jawaban @ bilobatum , dan menggunakan kategori ini dari pertanyaan lain. Saya memasak ini:

Pemakaian:

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;

Penerapan:

@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
Stian Høiland
sumber
Mengubah garis UIFont *fontForRange = [attributesForRange valueForKey:NSFontAttributeName];untuk UIFont *fontForRange = [attributesForRange valueForKey:NSFontAttributeName] ?: [UIFont fontWithName:@"HelveticaNeue" size:12.0];harus lebih baik, karena [attributesForRange valueForKey: NSFontAttributeName] mungkin nihil jika itu tidak diatur dalam kamus
Victor Kwok
5

Solusi masalah dalam contoh sederhana adalah masukkan deskripsi gambar di sini

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
Prabhat Kasera
sumber