Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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...

like image 746
Max Seelemann Avatar asked Sep 21 '10 13:09

Max Seelemann


3 Answers

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;
like image 182
Graham Perks Avatar answered Nov 07 '22 17:11

Graham Perks


Note: this is not available in iOS7:


I have discovered that you can create a subclass that re-implements [UITextView styleString]:

@interface UITextView ()
- (id)styleString; // make compiler happy
@end

@interface MBTextView : UITextView
@end
@implementation MBTextView
- (id)styleString {
    return [[super styleString] stringByAppendingString:@"; line-height: 1.2em"];
}
@end

This is not private API usage: it is just subclassing. It's possible Apple may disagree of course (though considering how we all used to swizzle everything in order to customize UIKit appearance, I feel that this kind of “private” usage is not what Apple object to), but it's such an easy way to achieve the goals of this question that you may as well try it. Should the app be rejected you can spend the (probably significant) time on a more difficult solution.

like image 22
mxcl Avatar answered Nov 07 '22 19:11

mxcl


In the Attribute Inspector for the UITextView instead change the property Text to Attributed (from Plain), and click the "more" button, there you can set the line height and spacing.

UITextView's Attribute Inspector

like image 21
Vegard Avatar answered Nov 07 '22 18:11

Vegard