How can I increase line space in UITextView so that it looks like "Notes" app in iPhone?
With Swift 4 and iOS 11, according to your needs, you can choose one of the 3 following implementations in order to solve your problem.
String
and UIFontDescriptorSymbolicTraits
traitLooseLeading
propertytraitLooseLeading
has the following declaration:
The font uses looser leading values.
static var traitLooseLeading: UIFontDescriptorSymbolicTraits { get }
The following code shows how to implement traitLooseLeading
in order to have a looser font leading for your UItextView
.
import UIKit
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
let textView = UITextView()
view.addSubview(textView)
textView.text = """
Lorem ipsum
Dolor sit amet,
consectetur adipiscing elit
"""
if let fontDescriptor = UIFontDescriptor
.preferredFontDescriptor(withTextStyle: UIFontTextStyle.body)
.withSymbolicTraits(UIFontDescriptorSymbolicTraits.traitLooseLeading) {
let looseLeadingFont = UIFont(descriptor: fontDescriptor, size: 0)
textView.font = looseLeadingFont
}
// Layout textView
textView.translatesAutoresizingMaskIntoConstraints = false
textView.topAnchor.constraint(equalTo: view.readableContentGuide.topAnchor).isActive = true
textView.bottomAnchor.constraint(equalTo: view.readableContentGuide.bottomAnchor).isActive = true
textView.leadingAnchor.constraint(equalTo: view.readableContentGuide.leadingAnchor).isActive = true
textView.trailingAnchor.constraint(equalTo: view.readableContentGuide.trailingAnchor).isActive = true
}
}
NSAttributedString
and NSMutableParagraphStyle
lineSpacing
propertylineSpacing
has the following declaration:
The distance in points between the bottom of one line fragment and the top of the next.
var lineSpacing: CGFloat { get set }
The following code shows how to implement lineSpacing
in order to have a specific line spacing for some attributed text in your UItextView
.
import UIKit
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
let string = """
Lorem ipsum
Dolor sit amet,
consectetur adipiscing elit
"""
let paragraphStyle = NSMutableParagraphStyle()
paragraphStyle.lineSpacing = 15
let attributes: [NSAttributedStringKey: Any] = [NSAttributedStringKey.paragraphStyle: paragraphStyle]
let attributedString = NSAttributedString(string: string, attributes: attributes)
let textView = UITextView()
textView.attributedText = attributedString
view.addSubview(textView)
// Layout textView
textView.translatesAutoresizingMaskIntoConstraints = false
textView.topAnchor.constraint(equalTo: view.readableContentGuide.topAnchor).isActive = true
textView.bottomAnchor.constraint(equalTo: view.readableContentGuide.bottomAnchor).isActive = true
textView.leadingAnchor.constraint(equalTo: view.readableContentGuide.leadingAnchor).isActive = true
textView.trailingAnchor.constraint(equalTo: view.readableContentGuide.trailingAnchor).isActive = true
}
}
String
and NSLayoutManagerDelegate
protocol layoutManager(_:lineSpacingAfterGlyphAt:withProposedLineFragmentRect:)
methodlayoutManager(_:lineSpacingAfterGlyphAt:withProposedLineFragmentRect:)
has the following declaration:
Returns the spacing after the line ending with the given glyph index. [...] This message is sent while each line is laid out to enable the layout manager delegate to customize the shape of line.
optional func layoutManager(_ layoutManager: NSLayoutManager, lineSpacingAfterGlyphAt glyphIndex: Int, withProposedLineFragmentRect rect: CGRect) -> CGFloat
The following code shows how to implement layoutManager(_:lineSpacingAfterGlyphAt:withProposedLineFragmentRect:)
in order to have a specific line spacing for your UItextView
.
import UIKit
class ViewController: UIViewController, NSLayoutManagerDelegate {
override func viewDidLoad() {
super.viewDidLoad()
let textView = UITextView()
textView.layoutManager.delegate = self
view.addSubview(textView)
textView.text = """
Lorem ipsum
Dolor sit amet,
consectetur adipiscing elit
"""
// Layout textView
textView.translatesAutoresizingMaskIntoConstraints = false
textView.topAnchor.constraint(equalTo: view.readableContentGuide.topAnchor).isActive = true
textView.bottomAnchor.constraint(equalTo: view.readableContentGuide.bottomAnchor).isActive = true
textView.leadingAnchor.constraint(equalTo: view.readableContentGuide.leadingAnchor).isActive = true
textView.trailingAnchor.constraint(equalTo: view.readableContentGuide.trailingAnchor).isActive = true
}
// MARK: - NSLayoutManagerDelegate
func layoutManager(_ layoutManager: NSLayoutManager, lineSpacingAfterGlyphAt glyphIndex: Int, withProposedLineFragmentRect rect: CGRect) -> CGFloat {
return 15
}
}
As an alternative to the previous code, the following code shows how to implement layoutManager(_:lineSpacingAfterGlyphAt:withProposedLineFragmentRect:)
in a UITextView
subclass.
import UIKit
class LineSpacingTextView: UITextView, NSLayoutManagerDelegate {
override init(frame: CGRect, textContainer: NSTextContainer?) {
super.init(frame: frame, textContainer: textContainer)
layoutManager.delegate = self
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
// MARK: - NSLayoutManagerDelegate
func layoutManager(_ layoutManager: NSLayoutManager, lineSpacingAfterGlyphAt glyphIndex: Int, withProposedLineFragmentRect rect: CGRect) -> CGFloat {
return 15
}
}
import UIKit
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
let textView = LineSpacingTextView()
view.addSubview(textView)
textView.text = """
Lorem ipsum
Dolor sit amet,
consectetur adipiscing elit
"""
// Layout textView
textView.translatesAutoresizingMaskIntoConstraints = false
textView.topAnchor.constraint(equalTo: view.readableContentGuide.topAnchor).isActive = true
textView.bottomAnchor.constraint(equalTo: view.readableContentGuide.bottomAnchor).isActive = true
textView.leadingAnchor.constraint(equalTo: view.readableContentGuide.leadingAnchor).isActive = true
textView.trailingAnchor.constraint(equalTo: view.readableContentGuide.trailingAnchor).isActive = true
}
}
Well now on iOS6, there is a possibility, using NSParagraphStyle
, but it is very poorly documented and seems to work seldomly.
I'm currently working about it like this:
UITextView *lab = [LocalTexts objectAtIndex:j];
NSMutableParagraphStyle *paragraphStyle = [[NSMutableParagraphStyle alloc] init];
paragraphStyle.lineHeightMultiple = 50.0f;
paragraphStyle.maximumLineHeight = 50.0f;
paragraphStyle.minimumLineHeight = 50.0f;
NSString *string = lab.text;
NSDictionary *ats = @{
NSFontAttributeName: [UIFont fontWithName:@"DIN Medium" size:16.0f],
NSParagraphStyleAttributeName: paragraphStyle,
};
lab.attributedText = [[NSAttributedString alloc] initWithString:string attributes:ats];
Problem is that when you set the Font, the line height stops working. Very odd. I haven't found a fix for it yet.
Also you can create a custom Attributed CoreText view... but it's a bit more technical, you can find a demo of how it is done here
Well I hope something helps.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With