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];

แต่ดูเหมือนว่าจะลอยอยู่เหนือข้อความและครอบคลุม

ฉันได้อ่านเกี่ยวกับเส้นทางการยกเว้นซึ่งดูเหมือนจะเป็นวิธีหนึ่งในการนำไปใช้ อย่างไรก็ตามฉันไม่ต้องการวางตำแหน่งรูปภาพอย่างแน่นอน แต่ควรไหลไปกับข้อความ (คล้ายกับวิธีการ<span>ทำงานใน HTML)


คำตอบบางส่วนกล่าวถึงโดยใช้คุณสมบัติรูปภาพบน NSTextAttachment และ NSTextField แต่ฉันต้องการพูดถึงว่าฉันต้องการโซลูชันที่ช่วยให้ฉันสามารถผนวก UIView ได้
Andy Hin

5
น่าทึ่งมากที่ฉันเพิ่งดู Royal Rumble 2011 เมื่อเช้านี้ (ซึ่งภาพของคุณถูกจับมาจาก) ผ่านเครือข่าย WWE และวันนี้ฉันก็เกิดคำถามนี้ขึ้นมา
bpapa

Heya คุณมีตัวอย่างโค้ดการทำงานที่เกี่ยวข้องกับ TextAttachment หรือไม่?
fatuhoku

คำตอบ:


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
Andy Hin

4
นี่ไม่ใช่การแสดงภาพเมื่อใช้สตริงผลลัพธ์ใน UITextView
DeepK SOreadytohelp

6
ฉันจะปรับขนาด NSTextAttachment ได้อย่างไร
jsetting32

2
@bilobatum ฉันต้องการเพิ่มมากกว่าหนึ่งภาพใน textview ฉันจะเพิ่มได้อย่างไร?
Diken Shah

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
Andy Hin

คุณอาจสามารถทำงานหลัก ๆ ในคลาสที่กำหนดเองได้ NSTextAttachment มีแอตทริบิวต์ภาพเริ่มต้นและสิ่งที่แนบมาจะถูกเก็บไว้เป็นส่วนหนึ่งของ NSAttributedString คุณอาจสร้างคลาสย่อยของคุณเองและจัดเก็บสิ่งที่คุณต้องการได้ ฉันคิดว่าการแสดงผล จำกัด เฉพาะการแสดงภาพดังนั้นไม่แน่ใจว่า UIView จะมีประโยชน์ ในขณะที่ฉันจำ layoutManager คาดหวังภาพ
Duncan Groenewald

1
@AndyHin ฉันไม่ได้ทดสอบด้วยตัวเอง แต่มีทางเลือกหนึ่งที่จะทำให้คุณUIViewเป็น a UIImageแล้วเพิ่มเป็นNSTextAttachmentไฟล์. ในการแสดงผลการดูภาพให้ลองดูคำถามนี้: http://stackoverflow.com/questions/4334233/how-to-capture-uiview-to-uiimage-without-loss-of-quality-on-retina- display? lq = 1
Michael Gaylord

การพัฒนาใหม่ ๆ เกี่ยวกับสิ่งนี้หรือไม่?
fatuhoku

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] อาจไม่มีค่าหากไม่ได้ตั้งค่าไว้ในพจนานุกรม
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
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.