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.
Енді Хін

5
Дивовижно, що я щойно дивився Королівський гуркіт 2011 року цього ранку (де було захоплено ваше зображення) через мережу WWE, і ось я сьогодні з цим питанням.
бпапа

Хея, у вас є приклад деякого робочого коду, що включає TextAttachment?
фатухоку

Відповіді:


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

6
Як змінити розмір NSTextAttachment?
jsetting32

2
@bilobatum, я хочу додати більше зображень до перегляду тексту. Так як я можу додати?
Дікен Шах

3
`[attributedString insertAttributedString: textAttachment atIndex: 4]` краще, ніжreplaceCharactersInRange
DawnSong

26

@ код білобату, перетворений на 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 очікує зображення.
Данкан Гроневальд

1
@AndyHin Я ще не перевіряв це, але один варіант, можливо, візуалізує ваш UIViewа, UIImageа потім додати його як NSTextAttachment. Щоб надати зображення зображенню, перегляньте це питання: http://stackoverflow.com/questions/4334233/how-to-capture-uiview-to-uiimage-without-loss-of-quality-on-retina- показ? lq = 1
Майкл Гейлорд

Якісь нові розробки з цим?
фатухоку

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] може бути нуль , якщо він не був встановлений в словнику
Віктор Квок

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
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.