30

I want to align vertically the text inside my UITextView (so it will be in the middle of it). How can i achieve that? I looked up and could not find any answer that could help me.

Thanks in advance.

mike vorisis
  • 2,786
  • 6
  • 40
  • 74
Volkan
  • 339
  • 1
  • 3
  • 8
  • You have to be more specific do you want to do it from storyboard or from code and if you want from code what version of swift do you use? – mike vorisis Dec 29 '16 at 21:54
  • I use Swift 3. It would be better if it was from storyboard but i couldn't see an option for that – Volkan Dec 29 '16 at 21:57

8 Answers8

61

Link your Text View to your View Controller and name it as you want (let's say textView).

In viewDidLayoutSubviews function put this line:

textView.centerVertically()

Then under the last curly bracket of your class put this extension:

extension UITextView {
    func centerVertically() {
        let fittingSize = CGSize(width: bounds.width, height: CGFloat.greatestFiniteMagnitude)
        let size = sizeThatFits(fittingSize)
        let topOffset = (bounds.size.height - size.height * zoomScale) / 2
        let positiveTopOffset = max(1, topOffset)
        contentOffset.y = -positiveTopOffset
    }   
}

To use this function in Swift 2.0 just change CGFloat.greatestFiniteMagnitude to CGFloat.max

אורי orihpt
  • 2,358
  • 2
  • 16
  • 41
mike vorisis
  • 2,786
  • 6
  • 40
  • 74
  • I want to center it 'vertically' in the container not 'horizontally' – Volkan Dec 29 '16 at 22:04
  • @Volkan what do you mean vertically? – mike vorisis Dec 29 '16 at 22:05
  • 1
    lets say i have a text for 2 lines only and my textview has a height for 200. I want to center that text vertically – Volkan Dec 29 '16 at 22:06
  • There is no alignment specifically for vertical orientation. However, there are a number of strategies you can deploy see here: http://stackoverflow.com/questions/1054558/vertically-align-text-to-top-within-a-uilabel – Yohst Dec 29 '16 at 22:08
  • @Volkan I edited my answer, use this extension and you will be good to go! Remember to accept the answer if it works thanks. – mike vorisis Dec 29 '16 at 22:35
  • 4
    this answer is good, just put that code in layoutsubviews of the superview or viewdidlayoutsubviews in the controller – Stan Jul 24 '17 at 09:58
  • 1
    But this answer doesn't support multiline well no? – Happiehappie Mar 14 '19 at 09:00
  • @Happiehappie I updated my answer as stan said you have to put this code inside viewdidlayoutsubviews to perfectly work. – mike vorisis Mar 14 '19 at 09:58
  • and also, if you set new value to the .text also need to call method – miff Sep 06 '19 at 07:34
  • How do I use this in a separate class that creates a multiline UITextView? I tried putting ````textView.centerVertically()```` in ````override func layoutSubviews()```` but it doesn't work. – Greg Sep 29 '20 at 14:45
  • @Greg Hi, are you trying to use it inside a cell or controller? Do you get an error or you don't see any change after you run it? Finally either you using `layoutSubviews` or `viewDidLayoutSubviews` you have to call `super.layoutSubviews` or `super.viewDidLayoutSubviews` before you call the method. – mike vorisis Oct 06 '20 at 08:11
  • @mike vorisis, no, unfortunately, same problem with or without ````super.layoutSubviews()````. I can show you my code if you can tell me how to do so. – Greg Oct 06 '20 at 15:30
  • @Greg so I understand you tried to use it in a cell not a controller right? (I didnt try this in a cell try to use it inside draw) – mike vorisis Oct 07 '20 at 08:17
  • @mike vorisis - forgive me, I'm new with Xcode and Swift and some of the terminology has me baffled. It is inside ````class CreateTables: UIView{ ... }```` created by a ViewController. – Greg Oct 07 '20 at 19:57
  • Ok try to put it inside the draw (with super) – mike vorisis Oct 08 '20 at 22:03
4

src: https://github.com/soonin/IOS-Swift-UITextViewAlignTextVertically/blob/master/IOS-Swift-UITextViewAlignTextVertically/Extentions.swift

extension UITextView {
    func centerVerticalText() {
        var topCorrect = (self.bounds.size.height - self.contentSize.height * self.zoomScale) / 2
        topCorrect = topCorrect < 0.0 ? 0.0 : topCorrect
        self.contentInset.top = topCorrect
    }
 }

Edit: It's recommended to call it in layoutSubviews()

Levan Karanadze
  • 739
  • 1
  • 11
  • 21
  • Thank you ! The accepted answer did not allow me to scroll the textView while yours did ( I just had to call it in layoutSubview and it was okay) – benjiii Feb 02 '22 at 11:31
2

If you want to do this using the storyboard, you could add a view inside of your textView. Then, set the constraints that you used for the textView to the new view. Finally, add the following constraints to your text view:

  • (right and left) O and point to the new view
  • using the alignment constraints, add a vertically constraint.

    enter image description here

Christian
  • 773
  • 7
  • 11
  • 1
    You can't put an UIView inside of UITextView. – Farkas Antal Apr 28 '20 at 16:37
  • Ahh this is really smart. He's saying put a textview (vertically aligned) inside a "parent" view. – Eric Oct 23 '22 at 02:58
  • 1
    This totally worked for me and was very easy to do. UNDERRATED ANSWER. I was would recommend having the "parent" view being a horizontal stack view, then set the alignment to "centered" so that the text view's height automatically adjusts to always keep it centered. – Eric Oct 23 '22 at 03:17
2

The above answer is correct, just want to add solution for those updating the textView on real time/onEditing.

Use the above extension and add the delegate method as well.

func textViewDidChange(_ textView: UITextView) { textView.centerVertically() }

Raza.najam
  • 769
  • 6
  • 15
2

Swift 5

Put the following extension below your last curly bracket in your ViewController:

// MARK: - UITextView extension
extension UITextView {

    func centerVerticalText() {
        self.textAlignment = .center
        let fitSize = CGSize(width: bounds.width, height: CGFloat.greatestFiniteMagnitude)
        let size = sizeThatFits(fitSize)
        let calculate = (bounds.size.height - size.height * zoomScale) / 2
        let offset = max(1, calculate)
        contentOffset.y = -offset
    }
}

Call this function after you set the text.

yourTextView.centerVerticalText()
Farkas Antal
  • 310
  • 3
  • 9
1

Add this to your extension or extending class of UITextView

public func centerVertically()
{
    let iFont = font == nil ? UIFont.systemFont(ofSize: UIFont.systemFontSize) : font!
    textContainerInset.top = (frame.height - iFont.lineHeight) / 2
}
Ben Levi
  • 177
  • 1
  • 5
0

textContainerInset worked for me instead of contentOffset.

extension UITextView {
    func centerVertically() {
        let fittingSize = CGSize(width: bounds.width, height: CGFloat.greatestFiniteMagnitude)
        let size = sizeThatFits(fittingSize)
        let topOffset = (bounds.size.height - size.height * zoomScale) / 2
        let positiveTopOffset = max(1, topOffset)
        textContainerInset.top = positiveTopOffset
    }
}
Water
  • 540
  • 7
  • 7
-1

This is used to center the text horizontal.

maiordache
  • 34
  • 3