-
Swift UILabel 텍스트 부분 색상/폰트/볼드/밑줄 적용하기🧑💻/Swift 2023. 3. 1. 18:30반응형
개발하다 보면 특정 부분에 볼드되거나 색상 변경, 밑줄이 들어가는 경우가 종종 있습니다.
공통적으로 사용할 수 있기 때문에 UILabel을 extension하여 구현해 두면 요긴하게 쓸 수 있죠!위 예시를 보면 "지날 달 보러가기" 는 밑줄을,
"감정 카드 저장을 원하시면 설정에서 사진 접근을 허용하세요." 는 부분 볼드 처리를 해야합니다.각 함수를 구현하기 전 개념을 짚고 넘어가 봅시다~
개념 이해하기
부분 적용을 위해서는 UILabel의 attributedText를 설정해야합니다.
아래 코드는 UIKit.UILabel을 발췌했습니다.
attributedText의 주석을 보시면 'attributedText 지정 시 text, font, textColor 등 모든 속성이 무시된다' 고 하네요.import Foundation // // UILabel.h // UIKit // // Copyright (c) 2006-2018 Apple Inc. All rights reserved. // @available(iOS 2.0, *) @MainActor open class UILabel : UIView, NSCoding, UIContentSizeCategoryAdjusting { open var text: String? // default is nil open var font: UIFont! // default is nil (system font 17 plain) open var textColor: UIColor! // default is labelColor open var shadowColor: UIColor? // default is nil (no shadow) open var shadowOffset: CGSize // default is CGSizeMake(0, -1) -- a top shadow open var textAlignment: NSTextAlignment // default is NSTextAlignmentNatural (before iOS 9, the default was NSTextAlignmentLeft) open var lineBreakMode: NSLineBreakMode // default is NSLineBreakByTruncatingTail. used for single and multiple lines of text // the underlying attributed string drawn by the label, if set, the label ignores the properties above. @available(iOS 6.0, *) @NSCopying open var attributedText: NSAttributedString? // default is nil
UILabel text를 AttributedString으로 변환하기
그렇다면 attributedText를 지정하면 그 전에 내가 설정한 모든 속성 값이 초기화 된다는 말인데...
초기화 되는 문제를 미연에 방지하기 위해
내가 설정한 text와 font를 attributedString으로 바꾸어 주는 함수를 추가했습니다.import UIKit extension UILabel { /* AttributedString이 설정되어있지 않으면 생성하여 반환한다. */ private func mutableAttributedString() -> NSMutableAttributedString? { guard let labelText = self.text, let labelFont = self.font else { return nil } var attributedString: NSMutableAttributedString? if let attributedText = self.attributedText { attributedString = attributedText.mutableCopy() as? NSMutableAttributedString } else { attributedString = NSMutableAttributedString(string: labelText, attributes: [NSAttributedString.Key.font :labelFont]) } return attributedString } }
더 많은 NSAttributedString.key를 보고 싶다면 공식 문서를 참고해주세요.
UILabel 특정 부분 Color 지정하기
color 지정은 UILabel.textColor로 지정할 수 있지만 부분 컬러를 지정하기 위해 NSRange 타입을 parameter로 받았습니다.
먼저 attributedString으로 변환한 뒤 NSAttributedString.key.foregroundColor를 해당 범위만큼만 다른 색상으로 대체합니다.extension UILabel { /* 텍스트 구간 색상 변경 */ func setTextColor(_ color: UIColor, range: NSRange) { guard let attributedString = self.mutableAttributedString() else { return } attributedString.addAttribute(NSAttributedString.Key.foregroundColor, value: color, range: range) self.attributedText = attributedString } /* AttributedString이 설정되어있지 않으면 생성하여 반환한다. */ private func mutableAttributedString() -> NSMutableAttributedString? { guard let labelText = self.text, let labelFont = self.font else { return nil } var attributedString: NSMutableAttributedString? if let attributedText = self.attributedText { attributedString = attributedText.mutableCopy() as? NSMutableAttributedString } else { attributedString = NSMutableAttributedString(string: labelText, attributes: [NSAttributedString.Key.font :labelFont]) } return attributedString } }
UILabel 특정 부분 Font 지정하기
Color 지정과 유사하게, NSAttributedString.key.font를 적용합니다.
extension UILabel { /* 텍스트 구간 폰트 변경 */ func setFont(_ font: UIFont, range: NSRange) { guard let attributedString = self.mutableAttributedString() else { return } attributedString.addAttribute(NSAttributedString.Key.font, value: font, range: range) self.attributedText = attributedString } /* 텍스트 구간 볼드 폰트 변경 */ func setBoldFont(_ boldFontName: String, range: NSRange) { guard let font = self.font, let boldFont = UIFont(name: boldFontName, size: font.pointSize) else { return } return setFont(boldFont, range: range) } /* AttributedString이 설정되어있지 않으면 생성하여 반환한다. */ private func mutableAttributedString() -> NSMutableAttributedString? { guard let labelText = self.text, let labelFont = self.font else { return nil } var attributedString: NSMutableAttributedString? if let attributedText = self.attributedText { attributedString = attributedText.mutableCopy() as? NSMutableAttributedString } else { attributedString = NSMutableAttributedString(string: labelText, attributes: [NSAttributedString.Key.font :labelFont]) } return attributedString } }
UILabel 특정 부분 밑줄(Underline) 지정하기
NSAttributedString.key.underlineStyle로 밑줄을 적용합니다.
NSUnderlineStyle의 rawValue (int)를 넣어주면 됩니다.extension UILabel { /* 밑줄 추가 */ func setUnderline(range: NSRange) { guard let attributedString = self.mutableAttributedString() else { return } attributedString.addAttribute(NSAttributedString.Key.underlineStyle, value: NSUnderlineStyle.single.rawValue, range: range) self.attributedText = attributedString } /* AttributedString이 설정되어있지 않으면 생성하여 반환한다. */ private func mutableAttributedString() -> NSMutableAttributedString? { guard let labelText = self.text, let labelFont = self.font else { return nil } var attributedString: NSMutableAttributedString? if let attributedText = self.attributedText { attributedString = attributedText.mutableCopy() as? NSMutableAttributedString } else { attributedString = NSMutableAttributedString(string: labelText, attributes: [NSAttributedString.Key.font :labelFont]) } return attributedString } }
사용할 때는 UIButton의 titleLabel인 경우 아래와 같이 전체 밑줄을 줄 수 있습니다.
btnLastMonth.titleLabel?.setUnderline(range: NSRange(location: 0, length: btnLastMonth.currentTitle?.count ?? 0))
전체 코드
import UIKit extension UILabel { /* 텍스트 구간 색상 변경 */ func setTextColor(_ color: UIColor, range: NSRange) { guard let attributedString = self.mutableAttributedString() else { return } attributedString.addAttribute(NSAttributedString.Key.foregroundColor, value: color, range: range) self.attributedText = attributedString } /* 텍스트 구간 볼드 폰트 변경 */ func setBoldFont(_ boldFontName: String, range: NSRange) { guard let font = self.font, let boldFont = UIFont(name: boldFontName, size: font.pointSize) else { return } return setFont(boldFont, range: range) } /* 텍스트 구간 폰트 변경 */ func setFont(_ font: UIFont, range: NSRange) { guard let attributedString = self.mutableAttributedString() else { return } attributedString.addAttribute(NSAttributedString.Key.font, value: font, range: range) self.attributedText = attributedString } /* 밑줄 추가 */ func setUnderline(range: NSRange) { guard let attributedString = self.mutableAttributedString() else { return } attributedString.addAttribute(NSAttributedString.Key.underlineStyle, value: NSUnderlineStyle.single.rawValue, range: range) self.attributedText = attributedString } /* AttributedString이 설정되어있지 않으면 생성하여 반환한다. */ private func mutableAttributedString() -> NSMutableAttributedString? { guard let labelText = self.text, let labelFont = self.font else { return nil } var attributedString: NSMutableAttributedString? if let attributedText = self.attributedText { attributedString = attributedText.mutableCopy() as? NSMutableAttributedString } else { attributedString = NSMutableAttributedString(string: labelText, attributes: [NSAttributedString.Key.font :labelFont]) } return attributedString } }
반응형