NSTextAttachment image alignment

8.1k views Asked by At

I am following this cool tutorial Implementing Rich Text with Images on OS X and iOS by @Duncan Groenewald and was able to display images in my UITextView. However, these images are not centered they way I would like them to be. See image

NSTextAttachment sample image

As you can see, I would like my image to be centered on the X-axis.

I tried returning the rect with appropriate values in -attachmentBoundsForTextContainer:proposedLineFragment:glyphPosition:characterIndex but that did not help.

I also tried setting the NSKernAttributeName for the NSTextAttachment attributed string. But all it did was hide the image some how.

3

There are 3 answers

0
Luca Davanzo On

This is Swift 3.1 using extension:

extension NSMutableAttributedString {

    func setAttachmentsAlignment(_ alignment: NSTextAlignment) {
        self.enumerateAttribute(NSAttachmentAttributeName, in: NSRange(location: 0, length: self.length), options: .longestEffectiveRangeNotRequired) { (attribute, range, stop) -> Void in
            if attribute is NSTextAttachment {
                let paragraphStyle = NSMutableParagraphStyle()
                paragraphStyle.alignment = alignment
                self.addAttribute(NSParagraphStyleAttributeName, value: paragraphStyle, range: range)
            }
        }
    }

}

In this way you can you easily apply alignment for attachments on attributed string:

let attributeString = NSMutableAttributedString(string: "")
// add attachments
attributeString.setAttachmentsAlignment(.center) 
0
Fredrik Johansson On

Here's another way how to set the alignment for an NSTextAttachment image. Hopefully this will also help someone struggling with this. I'm using the code below in a func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell

var buttonText = "My Button";

let align = NSMutableParagraphStyle();
align.alignment = NSTextAlignment.center;
align.firstLineHeadIndent = 10.0;
align.headIndent = 10.0;
align.tailIndent = -10.0;

let para = NSMutableAttributedString();

// top padding
para.append(NSAttributedString(string: "\n", attributes: [NSParagraphStyleAttributeName: align, NSFontAttributeName: UIFont(name: "Helvetica", size: 10.0)!, NSForegroundColorAttributeName: UIColor.white]));

// image
let img = NSTextAttachment();
img.image = UIImage(named: "MyIcon");
img.bounds = CGRect(x: 0, y: UIFont(name: "Helvetica", size: 18.0)!.descender, width: img.image!.size.width, height: img.image!.size.height);
let nas = NSAttributedString(attachment: img).mutableCopy() as! NSMutableAttributedString;
nas.addAttribute(NSParagraphStyleAttributeName, value: align, range: NSRange(location: 0, length: nas.length));
para.append(nas);

// space to text
buttonText = " " + buttonText;

// text
para.append(NSAttributedString(
    string: buttonText,
    attributes: [NSParagraphStyleAttributeName: align, NSFontAttributeName: UIFont(name: "Helvetica", size: 18.0)!, NSForegroundColorAttributeName: UIColor.black]));

// bottom padding
para.append(NSAttributedString(string: "\n", attributes: [NSParagraphStyleAttributeName: align, NSFontAttributeName: UIFont(name: "Helvetica", size: 10.0)!, NSForegroundColorAttributeName: UIColor.white]));

// set cell label
let label = cell.textLabel!;
label.numberOfLines = 0;
label.layer.borderWidth = 0;
label.layer.masksToBounds = false;
label.backgroundColor = UIColor.clear;
label.layer.backgroundColor = UIColor.green;
label.attributedText = para;
0
Alex Choi On

Try setting the paragraph style on your attachment with a center alignment.

If your images are embedded in an attributed string as attachments, you can access them by enumerating through the attributed string's attachment attributes. For example:

    attributedContent.enumerateAttribute(NSAttachmentAttributeName, inRange: NSRange(location: 0, length: attributedContent.length), options: nil) { (attribute, range, stop) -> Void in
        if let attachment = attribute as? NSTextAttachment {

            // this example assumes you want to center all attachments. You can provide additional logic here. For example, check for attachment.image.

            let paragraphStyle = NSMutableParagraphStyle()
            paragraphStyle.alignment = .Center
            attributedContent.addAttribute(NSParagraphStyleAttributeName, value: paragraphStyle, range: range)
        }
    }