Search code examples
iosswiftuitextviewnstextattachment

Vertically center NSTextAttachment in a UITextView


I have an custom NSTextAttachment class which I use to scale images inside a UITextView (based on the answer here). This works great in portrait mode. In landscape mode, the images do not cover the whole screen and I want to center them in the textview.

Making changes to the bounds in the custom class (in attachmentBoundsForTextContainer:) does not make a difference (tried changing both x and y in the bounds). How else can this be changed? Thanks.


Solution

  • Vertically center the content of a UITextView.

    In viewWillAppear of your UIViewController.

    textView.addObserver(self, forKeyPath: "contentSize", options: .New, context: nil)
    

    In viewWillDisappear of your UIViewController.

    textView.removeObserver(self, forKeyPath: "contentSize")
    

    Override observeValueForKeyPath in your UIViewController.

    override func observeValueForKeyPath(keyPath: String?, ofObject object: AnyObject?, change: [String : AnyObject]?, context: UnsafeMutablePointer<Void>) {
    
        if keyPath == "contentSize" {
    
            let height = textView.bounds.size.height
            let contentHeight = textView.contentSize.height
            let zoom = textView.zoomScale
            let top = (height - contentHeight * zoom) / 2.0
            textView.contentInset.top = top < 0.0 ? 0.0 : top
        }
    }
    

    Horizontally center the content of an NSAttributtedString inside a UITextView.

    let attachment = NSTextAttachment()
    let attachmentAttrString = NSAttributedString(attachment: attachment)
    let result = NSMutableAttributedString(attributedString: attachmentAttrString)
    
    let paragraphStyle = NSMutableParagraphStyle()
    paragraphStyle.alignment = .Center
    
    let attrs:[String:AnyObject] = [NSParagraphStyleAttributeName: paragraphStyle]
    let range = NSMakeRange(0, result.length)
    result.addAttributes(attrs, range: range)
    
    textView.attributedText = result