В Swift 4 и iOS 11, в зависимости от ваших потребностей, вы можете выбрать одну из 3 следующих реализаций , чтобы решить вашу проблему.
# 1. Использование String
и UIFontDescriptorSymbolicTraits
traitLooseLeading
свойство
traitLooseLeading
имеет следующую декларацию:
Шрифт использует более свободные начальные значения.
static var traitLooseLeading: UIFontDescriptorSymbolicTraits { get }
В следующем коде показано, как реализовать traitLooseLeading
, чтобы получить более свободный шрифт, ведущий к вашему 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
}
}
# 2. Использование NSAttributedString
и NSMutableParagraphStyle
lineSpacing
свойство
lineSpacing
имеет следующую декларацию:
Расстояние в пунктах между нижней частью одного фрагмента строки и вершиной следующей.
var lineSpacing: CGFloat { get set }
В следующем коде показано, как реализовать lineSpacing
, чтобы иметь определенный межстрочный интервал для некоторого приписанного текста в вашем 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
}
}
# 3. Используя String
и NSLayoutManagerDelegate
протокол layoutManager(_:lineSpacingAfterGlyphAt:withProposedLineFragmentRect:)
метод
layoutManager(_:lineSpacingAfterGlyphAt:withProposedLineFragmentRect:)
имеет следующую декларацию:
Возвращает интервал после строки, заканчивающейся указанным индексом глифа. [...] Это сообщение отправляется во время размещения каждой строки, чтобы делегат менеджера макета мог настроить форму линии.
optional func layoutManager(_ layoutManager: NSLayoutManager, lineSpacingAfterGlyphAt glyphIndex: Int, withProposedLineFragmentRect rect: CGRect) -> CGFloat
В следующем коде показано, как реализовать layoutManager(_:lineSpacingAfterGlyphAt:withProposedLineFragmentRect:)
чтобы иметь определенный межстрочный интервал для вашего 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
}
}
В качестве альтернативы предыдущему коду, следующий код показывает, как реализовать layoutManager(_:lineSpacingAfterGlyphAt:withProposedLineFragmentRect:)
в подклассе UITextView
.
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
}
}