[UIKit-11] NSAttributedString을 통해 예쁘게 스타일 잡아보기
NSAttributedString은 텍스트 자체에 스타일을 설정할 수 있는 텍스트 타입니다. 나는 이 것을 공부하기 전에 예를 들어 ‘이것은 iOS입니다.’ 라는 label이 있을 때 iOS만 큰 font로 강조를 하고 싶다면 여러개의 label을 생성해 iOS만 특별히 크게 해주고 stackview로 묶어버렸던 경험이 있다.
그러나 오늘 이것을 공부하고 난 후, 그러한 짓은 하지 않기로 하였다.
NSAttributedStrings를 통해 정말 여러가지를 할 수 있다.
NSAttributedString.key: Any 인 dictionary 형태를 가지고 있는데, key로 설정이 가능한 것은 font, paragraphStyle, foregroundColor, backgroundColor, underlineStyle, shadow, textEffect, underlineColor 등등.. 아주 많다.
애플 공식문서를 통해 더욱 많은 것들을 확인할 수 있다.확인하기
아래 예시 코드들을 잘 기억해두고, 적절할 때 아주 유용히 꺼내 쓰도록 하자.
(https://github.com/jrasmusson/swift-arcade/blob/master/Foundation/NSAttributedStrings/README.md 해당 사이트를 참조한 글 입니다.)
Paragraph
lazy var label: UILabel = {
let label = makeLabel()
label.attributedText = makeText()
return label
}()
func makeText() -> c {
let paragraphStyle = NSMutableParagraphStyle()
paragraphStyle.firstLineHeadIndent = 24
paragraphStyle.headIndent = 8
paragraphStyle.tailIndent = -8
paragraphStyle.lineSpacing = 4
paragraphStyle.alignment = .justified
paragraphStyle.paragraphSpacingBefore = 4
paragraphStyle.paragraphSpacing = 24 // end of paragraph
let attributes = [
NSAttributedString.Key.foregroundColor: UIColor.systemGray,
NSAttributedString.Key.font: UIFont.preferredFont(forTextStyle: .body),
NSAttributedString.Key.paragraphStyle: paragraphStyle
]
let rootString = NSMutableAttributedString(string: "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.\n", attributes: attributes)
let secondParagraph = NSAttributedString(string: "Vulputate enim nulla aliquet porttitor lacus. Ipsum suspendisse ultrices gravida dictum fusce ut placerat. In fermentum et sollicitudin ac orci phasellus egestas tellus. Eu facilisis sed odio morbi quis commodo odio.", attributes: attributes)
rootString.append(secondParagraph)
return rootString
}
Bolding
func makeText() -> NSAttributedString {
var plainTextAttributes = [NSAttributedString.Key: AnyObject]()
plainTextAttributes[.font] = UIFont.preferredFont(forTextStyle: .body)
var boldTextAttributes = [NSAttributedString.Key: AnyObject]()
boldTextAttributes[.font] = UIFont.preferredFont(forTextStyle: .body).withTraits(traits: [.traitBold]) // extension
let text = NSMutableAttributedString(string: "Please", attributes: plainTextAttributes)
text.append(NSAttributedString(string: " stay on this screen ", attributes: boldTextAttributes))
text.append(NSAttributedString(string: "while we activate your service. This process may take a few minutes.", attributes: plainTextAttributes))
return text
}
Image
func makeText() -> NSAttributedString {
let paragraphStyle = NSMutableParagraphStyle()
paragraphStyle.lineSpacing = 4
var headerTextAttributes = [NSAttributedString.Key: AnyObject]()
headerTextAttributes[.font] = UIFont.preferredFont(forTextStyle: .body).withTraits(traits: [.traitBold])
var subHeaderTextAttributes = [NSAttributedString.Key: AnyObject]()
subHeaderTextAttributes[.font] = UIFont.preferredFont(forTextStyle: .body)
subHeaderTextAttributes[.foregroundColor] = UIColor.systemGray
let rootString = NSMutableAttributedString(string: "Kevin Flynn", attributes: headerTextAttributes)
rootString.append(NSAttributedString(string: "\nFebruary 10 • San Francisco ", attributes: subHeaderTextAttributes))
rootString.addAttribute(NSAttributedString.Key.paragraphStyle, value: paragraphStyle, range: NSMakeRange(0, rootString.string.count))
// image
let attachment = NSTextAttachment()
attachment.image = UIImage(named: "globe_icon")
rootString.append(NSAttributedString(attachment: attachment))
// string height
let desiredWidth: CGFloat = 300
let rect = rootString.boundingRect(with: CGSize(width: desiredWidth, height: CGFloat.greatestFiniteMagnitude), options: [.usesLineFragmentOrigin, .usesFontLeading], context: nil)
attachment.bounds = CGRect(x: 0, y: -2, width: rect.height/2, height: rect.height/2)
return rootString
}
Kerning
let attributedText = NSMutableAttributedString(string: title, attributes: [
NSAttributedString.Key.font: UIFont.boldSystemFont(ofSize: 16),
NSAttributedString.Key.foregroundColor: UIColor.white,
NSAttributedString.Key.kern: 2
])
BaselineOffset
fileprivate extension String {
func formatted() -> NSAttributedString {
let dollarSignAttributes: [NSAttributedString.Key: Any] = [.font: UIFont.preferredFont(forTextStyle: .callout), .baselineOffset: 8]
let priceAttributes: [NSAttributedString.Key: Any] = [.font: UIFont.preferredFont(forTextStyle: .title1)]
let monthAttributes: [NSAttributedString.Key: Any] = [.font: UIFont.preferredFont(forTextStyle: .callout)]
let termAttributes: [NSAttributedString.Key: Any] = [.font: UIFont.preferredFont(forTextStyle: .footnote), .baselineOffset: 8]
let rootString = NSMutableAttributedString(string: "$", attributes: dollarSignAttributes)
let priceString = NSAttributedString(string: self, attributes: priceAttributes)
let monthString = NSAttributedString(string: "/mo", attributes: monthAttributes)
let termString = NSAttributedString(string: "1", attributes: termAttributes)
rootString.append(priceString)
rootString.append(monthString)
rootString.append(termString)
return rootString
}
}