Pertanyaan Pusatkan gambar NSTextAttachment di samping garis tunggal UILabel


Saya ingin menambahkan gambar NSTextAttachment ke string yang dikaitkan dan memusatkan secara vertikal.

Saya telah menggunakan kode berikut untuk membuat string saya

        NSMutableAttributedString *str = [[NSMutableAttributedString alloc] initWithString:DDLocalizedString(@"title.upcomingHotspots") attributes:attrs];
        NSTextAttachment *attachment = [[NSTextAttachment alloc] init];
        attachment.image = [[UIImage imageNamed:@"help.png"] imageScaledToFitSize:CGSizeMake(14.f, 14.f)];
        cell.textLabel.attributedText = [str copy];

Namun, gambar tampak sejajar dengan bagian atas label teks sel.

enter image description here

Bagaimana saya bisa mengubah rect di mana lampiran diambil?


74
2017-09-29 17:47


asal


Jawaban:


Anda dapat mengubah rektum dengan subclassing NSTextAttachment dan menimpa attachmentBoundsForTextContainer:proposedLineFragment:glyphPosition:characterIndex:. Contoh:

- (CGRect)attachmentBoundsForTextContainer:(NSTextContainer *)textContainer proposedLineFragment:(CGRect)lineFrag glyphPosition:(CGPoint)position characterIndex:(NSUInteger)charIndex {
    CGRect bounds;
    bounds.origin = CGPointMake(0, -5);
    bounds.size = self.image.size;
    return bounds;
}

Itu bukan solusi sempurna. Anda harus mencari tahu asal-mula Y-nya dan jika Anda mengubah font atau ukuran ikon, Anda mungkin ingin mengubah asal-Y. Tetapi saya tidak dapat menemukan cara yang lebih baik, kecuali dengan menempatkan ikon dalam tampilan gambar terpisah (yang memiliki kekurangannya sendiri).


40
2017-09-29 19:32



Mencoba - [NSTextAttachment bounds]. Tidak diperlukan subclass.

Untuk konteks, saya membuat a UILabel untuk digunakan sebagai gambar lampiran, lalu menetapkan batas seperti: attachment.bounds = CGRectMake(0, self.font.descender, attachment.image.size.width, attachment.image.size.height) dan garis dasar teks dalam gambar label dan teks dalam string yang diatribusikan sesuai keinginan.


84
2018-02-05 22:22



Anda dapat menggunakan capHeight font.

Objective-C

NSTextAttachment *icon = [[NSTextAttachment alloc] init];
UIImage *iconImage = [UIImage imageNamed:@"icon.png"];
[icon setBounds:CGRectMake(0, roundf(titleFont.capHeight - iconImage.size.height)/2.f, iconImage.size.width, iconImage.size.height)];
[icon setImage:iconImage];
NSAttributedString *iconString = [NSAttributedString attributedStringWithAttachment:icon];
[titleText appendAttributedString:iconString];

Cepat

let iconImage = UIImage(named: "icon.png")!
var icon = NSTextAttachment()
icon.bounds = CGRect(x: 0, y: (titleFont.capHeight - iconImage.size.height).rounded() / 2, width: iconImage.size.width, height: iconImage.size.height)
icon.image = iconImage
let iconString = NSAttributedString(attachment: icon)
titleText.append(iconString)

Gambar lampiran ditampilkan pada garis dasar teks. Dan sumbu y itu terbalik seperti sistem koordinat grafis inti. Jika Anda ingin memindahkan gambar ke atas, atur bounds.origin.y menjadi positif.

Gambar harus sejajar dengan pusat vertikal dengan batas atas teks. Jadi kita perlu mengaturnya bounds.origin.y untuk (capHeight - imageHeight)/2.

Menghindari beberapa efek bergerigi pada gambar, kita harus membulatkan bagian pecahan dari y. Tetapi font dan gambar biasanya kecil, bahkan perbedaan 1px membuat gambar tampak seperti tidak sejajar. Jadi saya menerapkan fungsi bulat sebelum membagi. Itu membuat bagian pecahan dari nilai y menjadi .0 atau .5

Dalam kasus Anda, tinggi gambar lebih besar daripada batas atas font. Tetapi Anda bisa menggunakan cara yang sama. Nilai offset y akan menjadi negatif. Dan itu akan ditata dari bawah garis dasar.

enter image description here


67
2017-07-18 08:12



Saya menemukan solusi sempurna untuk ini, bekerja seperti pesona untuk saya, namun Anda harus mencobanya sendiri (mungkin konstanta tergantung pada resolusi perangkat dan mungkin apa pun;)

func textAttachment(fontSize: CGFloat) -> NSTextAttachment {
    let font = UIFont.systemFontOfSize(fontSize) //set accordingly to your font, you might pass it in the function
    let textAttachment = NSTextAttachment()
    let image = //some image
    textAttachment.image = image
    let mid = font.descender + font.capHeight
    textAttachment.bounds = CGRectIntegral(CGRect(x: 0, y: font.descender - image.size.height / 2 + mid + 2, width: image.size.width, height: image.size.height))
    return textAttachment
}

Harus bekerja dan tidak boleh buram dengan cara apa pun (terima kasih CGRectIntegral)


56
2017-12-01 18:17



Bagaimana dengan:

CGFloat offsetY = -10.0;

NSTextAttachment *attachment = [NSTextAttachment new];
attachment.image = image;
attachment.bounds = CGRectMake(0, offsetY, attachment.image.size.width, attachment.image.size.height);

Tidak perlu subclassing


31
2018-04-29 21:11



@Travis benar bahwa offset adalah font descender. Jika Anda juga perlu skala gambar, Anda harus menggunakan subkelas dari NSTextAttachment. Di bawah ini adalah kode, yang terinspirasi oleh artikel ini. Saya juga mempostingnya sebagai inti.

import UIKit

class ImageAttachment: NSTextAttachment {
    var verticalOffset: CGFloat = 0.0

    // To vertically center the image, pass in the font descender as the vertical offset.
    // We cannot get this info from the text container since it is sometimes nil when `attachmentBoundsForTextContainer`
    // is called.

    convenience init(_ image: UIImage, verticalOffset: CGFloat = 0.0) {
        self.init()
        self.image = image
        self.verticalOffset = verticalOffset
    }

    override func attachmentBoundsForTextContainer(textContainer: NSTextContainer, proposedLineFragment lineFrag: CGRect, glyphPosition position: CGPoint, characterIndex charIndex: Int) -> CGRect {
        let height = lineFrag.size.height
        var scale: CGFloat = 1.0;
        let imageSize = image!.size

        if (height < imageSize.height) {
            scale = height / imageSize.height
        }

        return CGRect(x: 0, y: verticalOffset, width: imageSize.width * scale, height: imageSize.height * scale)
    }
}

Gunakan sebagai berikut:

var text = NSMutableAttributedString(string: "My Text")
let image = UIImage(named: "my-image")!
let imageAttachment = ImageAttachment(image, verticalOffset: myLabel.font.descender)
text.appendAttributedString(NSAttributedString(attachment: imageAttachment))
myLabel.attributedText = text

9
2018-03-22 22:33



Jika Anda memiliki kekuatan yang sangat besar dan ingin memusatkan gambar (pusat dari tinggi tutup) seperti saya coba ini

let attachment: NSTextAttachment = NSTextAttachment()
attachment.image = image
if let image = attachment.image{
    let y = -(font.ascender-font.capHeight/2-image.size.height/2)
    attachment.bounds = CGRect(x: 0, y: y, width: image.size.width, height: image.size.height).integral
}

Perhitungan y adalah seperti gambar di bawah ini

enter image description here

Perhatikan bahwa nilai y adalah 0 karena kami ingin gambar bergeser ke bawah dari asalnya

Jika Anda ingin berada di tengah-tengah label keseluruhan. Gunakan nilai y ini:

let y = -((font.ascender-font.descender)/2-image.size.height/2)

5
2018-04-03 19:10