iOS 7 TextKit - Metinle satır içi resimler nasıl eklenir?


109

Bir UITextView kullanarak aşağıdaki efekti elde etmeye çalışıyorum:

görüntü açıklamasını buraya girin

Temel olarak metin arasına bir resim eklemek istiyorum. Resim sadece 1 satır yer kaplayabilir, böylece kaydırmaya gerek kalmaz.

Alt görünüme bir UIView eklemeyi denedim:

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

Ama metnin üzerinde süzülüyor ve onu kapatıyor gibi görünüyor.

Bunu uygulamanın bir yolu gibi görünen dışlama yolları hakkında biraz okudum . Bununla birlikte, resmi kesinlikle konumlandırmak istemiyorum - bunun yerine metinle birlikte <span>akmalı (HTML'deki davranışına benzer ).


Cevaplardan birkaçı, NSTextAttachment ve NSTextField'daki image özelliklerini kullanmaktan bahsediyor, ancak bir UIView eklememe izin veren bir çözüme ihtiyacım olduğunu belirtmek istiyorum.
Andy Hin

5
Bu sabah Royal Rumble 2011'i (görüntünüzün alındığı yer) WWE ağı aracılığıyla izlediğim için şaşırtıcı ve işte bugün bu soru üzerine geliyorum.
bpapa

Heya, TextAttachment'ı içeren bir çalışma kodu örneğiniz var mı?
fatuhoku

Yanıtlar:


180

Nitelikli bir dize kullanmanız ve görüntüyü şunun örneği olarak eklemeniz gerekir 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
Sanırım şu ana kadar en yakın cevap bu. Aynı tekniği UIImage yerine UIView ile kullanmak mümkün müdür?
Andy Hin

4
UITextView
DeepK SOreadytohelp

6
NSTextAttachment'ı nasıl yeniden boyutlandırırım?
jsetting32

2
@bilobatum, metin görünümüne birden fazla resim eklemek istiyorum. Peki nasıl ekleyebilirim?
Diken Shah

3
"[attributedString insertAttributedString: textAttachment atIndex: 4]" daha iyireplaceCharactersInRange
DawnSong

26

@ bilobatum'un kodu, ihtiyacı olanlar için Swift'e çevrildi:

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 ve NSTextAttachment'ı kullanmayı deneyebilirsiniz. Görüntüyü yeniden boyutlandırmak için NSTextAttachment'ı özelleştirme hakkında daha fazla ayrıntı için aşağıdaki bağlantıya bir göz atın. http://ossh.com.au/design-and-technology/software-development/implementing-rich-text-with-images-on-os-x-and-ios/

Örneğimde, genişliğe uyması için resmi yeniden boyutlandırıyorum, sizin durumunuzda görüntüyü satır yüksekliğine uyacak şekilde yeniden boyutlandırmak isteyebilirsiniz.


Sanırım şu ana kadar en yakın cevap bu. Aynı tekniği UIImage yerine UIView ile kullanmak mümkün müdür?
Andy Hin

Kendi özel sınıflarınız üzerinde bazı büyük çalışmalar yapabilirsiniz. NSTextAttachment varsayılan bir görüntü özniteliğine sahiptir ve ek, NSAttributedString'in bir parçası olarak saklanır. Muhtemelen kendi alt sınıflarınızı oluşturabilir ve istediğinizi saklayabilirsiniz. Bence ekran bir görüntüyü göstermekle sınırlı, bu yüzden bir UIView'ın yararlı olacağından emin değil. Hatırladığım kadarıyla layoutManager bir görüntü bekliyor.
Duncan Groenewald

1
Ben kendimi bu test değil ama bir seçenek oluşturmak için muhtemelen olduğu @AndyHin UIViewbir etmek UIImageve daha sonra bir olarak ekleyin NSTextAttachment. Görünümü bir görüntüye dönüştürmek için şu soruyu kontrol edin: http://stackoverflow.com/questions/4334233/how-to-capture-uiview-to-uiimage-without-loss-of-quality-on-retina- ekran? lq = 1
Michael Gaylord

Bununla ilgili yeni gelişmeler var mı?
fatuhoku

5

@ Bilobatum'un cevabını genişletmek ve bu kategoriyi başka bir sorudan kullanmak. Bunu ben pişirdim:

Kullanım:

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;

Uygulama:

@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

Çizgi değiştirme UIFont *fontForRange = [attributesForRange valueForKey:NSFontAttributeName];için UIFont *fontForRange = [attributesForRange valueForKey:NSFontAttributeName] ?: [UIFont fontWithName:@"HelveticaNeue" size:12.0];, daha iyi olacağı için [attributesForRange valueForKey: NSFontAttributeName] o sözlükte ayarlanmamış ise nil olabilir
Victor Kwok

5

Basit bir örnekte problem çözümü görüntü açıklamasını buraya girin

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
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.