Center NSTextAttachment image next to single line UILabel

后端 未结 10 1095
太阳男子
太阳男子 2020-11-30 16:51

I\'d like to append an NSTextAttachment image to my attributed string and have it centered vertically.

I\'ve used the following code to create my string

相关标签:
10条回答
  • 2020-11-30 17:08

    Please use -lineFrag.size.height/5.0 for the bounds height. This exactly centres the image and aligned with text for all the size of fonts

    override func attachmentBoundsForTextContainer(textContainer: NSTextContainer, proposedLineFragment lineFrag: CGRect, glyphPosition position: CGPoint, characterIndex charIndex: Int) -> CGRect
    {
        var bounds:CGRect = CGRectZero
    
        bounds.size = self.image?.size as CGSize!
        bounds.origin = CGPointMake(0, -lineFrag.size.height/5.0);
    
        return bounds;
    }
    
    0 讨论(0)
  • 2020-11-30 17:11

    I found a perfect solution to this, works like a charm for me though, however you have to try it out yourself (probably the constant depends on the resolution of the device and maybe whatever ;)

    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
    }
    

    Should work and shouldn't be blurry in any way (thanks to CGRectIntegral)

    0 讨论(0)
  • 2020-11-30 17:14

    In my case calling sizeToFit() helped. In swift 5.1

    Inside your custom label:

    func updateUI(text: String?) {
        guard let text = text else {
            attributedText = nil
            return
        }
    
        let attributedString = NSMutableAttributedString(string:"")
    
        let textAttachment = NSTextAttachment ()
        textAttachment.image = image
    
        let sizeSide: CGFloat = 8
        let iconsSize = CGRect(x: CGFloat(0),
                               y: (font.capHeight - sizeSide) / 2,
                               width: sizeSide,
                               height: sizeSide)
        textAttachment.bounds = iconsSize
    
        attributedString.append(NSAttributedString(attachment: textAttachment))
        attributedString.append(NSMutableAttributedString(string: text))
        attributedText = attributedString
    
        sizeToFit()
    }
    
    0 讨论(0)
  • 2020-11-30 17:20

    You can change the rect by subclassing NSTextAttachment and overriding attachmentBoundsForTextContainer:proposedLineFragment:glyphPosition:characterIndex:. Example:

    - (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;
    }
    

    It's not a perfect solution. You have to figure out the Y-origin “by eye” and if you change the font or the icon size, you'll probably want to change the Y-origin. But I couldn't find a better way, except by putting the icon in a separate image view (which has its own disadvantages).

    0 讨论(0)
  • 2020-11-30 17:24

    Try - [NSTextAttachment bounds]. No subclassing required.

    For context, I am rendering a UILabel for use as the attachment image, then setting the bounds like so: attachment.bounds = CGRectMake(0, self.font.descender, attachment.image.size.width, attachment.image.size.height) and baselines of text within label image and text in attributed string line up as desired.

    0 讨论(0)
  • 2020-11-30 17:27

    What about:

    CGFloat offsetY = -10.0;
    
    NSTextAttachment *attachment = [NSTextAttachment new];
    attachment.image = image;
    attachment.bounds = CGRectMake(0.0, 
                                   offsetY, 
                                   attachment.image.size.width, 
                                   attachment.image.size.height);
    

    No subclassing needed

    0 讨论(0)
提交回复
热议问题