Search code examples
iphonecocoa-touch

Set line height in UITextView


I'm already pretty sure that it can't be done with any public API, but I still want to ask:

Is there any way to change the line height in a UITextView?

Would be enough to do it statically, no need to change it at runtime. The problem is that the default line height is just WAY too small. Text will look extremely compressed and is a nightmare when trying to write longer texts.

thanks, Max

EDIT: I know that there is UIWebView and that it's nice and can do styling etc. But it's not editable. I need a editable text component with acceptable line height. That thing from the Omni Frameworks doesn't help either, as it's too slow and doesn't feel right...


Solution

  • After iOS 7, the styleString approach no longer works.

    Two new alternatives are available.

    Firstly, TextKit; a powerful new layout engine. To change line spacing, set the UITextView's layout manager's delegate:

    textView.layoutManager.delegate = self; // you'll need to declare you implement the NSLayoutManagerDelegate protocol
    

    Then override this delegate method:

    - (CGFloat)layoutManager:(NSLayoutManager *)layoutManager lineSpacingAfterGlyphAtIndex:(NSUInteger)glyphIndex withProposedLineFragmentRect:(CGRect)rect
    {
        return 20; // For really wide spacing; pick your own value
    }
    

    Secondly, iOS 7 now supports NSParagraphStyle's lineSpacing. This gives even more control, e.g. first line indentation, and calculation of a bounding rect. So alternatively...

    NSMutableParagraphStyle *paragraphStyle = [[NSMutableParagraphStyle alloc] init];
    paragraphStyle.headIndent = 15; // <--- indention if you need it
    paragraphStyle.firstLineHeadIndent = 15;
    
    paragraphStyle.lineSpacing = 7; // <--- magic line spacing here!
    
    NSDictionary *attrsDictionary =
    @{ NSParagraphStyleAttributeName: paragraphStyle }; // <-- there are many more attrs, e.g NSFontAttributeName
    
    self.textView.attributedText = [[NSAttributedString alloc] initWithString:@"Hello World over many lines!" attributes:attrsDictionary];
    

    FWIW, the old contentInset method to align the text along the left edge of UITextView is also no use under iOS7. Instead, to remove the margin:

    textView.textContainer.lineFragmentPadding = 0;