일단 라벨에 더보기 기능을 넣고 싶었는데
한참을 헤매다가 안되어서...포기하고 한숨자고 다시 도전
열심히 구글링해보니 역시 해답은 여기!!!!
https://dy-yb.github.io/2022/UILabelSeeMore/
UILabel text에 더보기 붙이기
긴 글의 내용이 일정한 길이로 축약되어 나타나는 label 만들기
dy-yb.github.io
여기에서 참고해서 사용했다.
let memoLabel: UILabel = {
let label = UILabel()
label.text = """
remember my workout
asdfasdfasdfasdfasdfasdf
asdfasdfasdf
asdfasdfasdf
asdfasdf
"""
label.font = UIFont.systemFont(ofSize: 17, weight: .regular)
label.textColor = .white
label.numberOfLines = 3 // 세 줄까지만 표시
label.translatesAutoresizingMaskIntoConstraints = false
return label
}()
let seeMoreButton: UIButton = {
let button = UIButton(type: .system)
button.setTitle("더보기", for: .normal)
button.setTitleColor(.gray, for: .normal)
button.titleLabel?.font = UIFont.systemFont(ofSize: 15, weight: .regular)
button.translatesAutoresizingMaskIntoConstraints = false
return button
}()
먼저 라벨하나 추가하고 버튼 하나를 추가해야된다 ~ 키특키득
memoLabel.topAnchor.constraint(equalTo: goalLable.bottomAnchor, constant: 0),
memoLabel.trailingAnchor.constraint(equalTo: trailingAnchor, constant: -20),
memoLabel.leadingAnchor.constraint(equalTo: leadingAnchor, constant: 20),
seeMoreButton.trailingAnchor.constraint(equalTo: trailingAnchor, constant: -20),
seeMoreButton.bottomAnchor.constraint(equalTo: memoLabel.bottomAnchor), // 같은 줄에 위치하도록
// 초기 '더보기' 버튼 상태 설정
checkMemoLabel()
// 버튼 클릭 시 호출될 메서드 설정
seeMoreButton.addTarget(self, action: #selector(didTapSeeMore), for: .touchUpInside)
레이아웃은 나는 이렇게 잡았다.
// 메모라벨을 확인하고 더보기 기능 적용
private func checkMemoLabel() {
DispatchQueue.main.async {
self.memoLabel.addTrailing(with: "... ", moreText: "more", moreTextFont: UIFont.systemFont(ofSize: 15), moreTextColor: UIColor.gray)
}
}
// '더보기' 버튼 클릭 시 전체 텍스트 표시
@objc private func didTapSeeMore() {
if memoLabel.numberOfLines == 3 {
memoLabel.numberOfLines = 0 // 전체 텍스트 표시
seeMoreButton.setTitle("folding", for: .normal) // 버튼 제목을 "접기"로 변경
} else {
memoLabel.numberOfLines = 3 // 다시 3줄로 제한
seeMoreButton.setTitle("more", for: .normal) // 버튼 제목을 "더보기"로 변경
}
}
요렇게 함수를 붙쳐주면 된다. 라인은 나는 3개까지만 보여주고 싶어서 그렇게 했는데 알아서 변경하면된다.
extension UILabel {
func addTrailing(with trailingText: String, moreText: String, moreTextFont: UIFont, moreTextColor: UIColor) {
let readMoreText = trailingText + moreText
// Check if the text fits within the label
guard let originalText = self.text, self.numberOfLines == 2 else { return }
let visibleTextLength = self.visibleTextLength()
let truncatedText = (originalText as NSString).replacingCharacters(in: NSRange(location: visibleTextLength, length: originalText.count - visibleTextLength), with: "")
let attributedString = NSMutableAttributedString(string: truncatedText, attributes: [NSAttributedString.Key.font: self.font ?? UIFont.systemFont(ofSize: 17)])
let readMoreAttributedString = NSMutableAttributedString(string: readMoreText, attributes: [NSAttributedString.Key.font: moreTextFont, NSAttributedString.Key.foregroundColor: moreTextColor])
attributedString.append(readMoreAttributedString)
self.attributedText = attributedString
}
func visibleTextLength() -> Int {
guard let font = self.font else { return 0 }
let mode = self.lineBreakMode
let labelWidth = self.frame.size.width
let labelHeight = self.font.lineHeight * CGFloat(self.numberOfLines)
let size = CGSize(width: labelWidth, height: labelHeight)
let attributes = [NSAttributedString.Key.font: font]
let attributedText = NSAttributedString(string: self.text ?? "", attributes: attributes)
let textStorage = NSTextStorage(attributedString: attributedText)
let layoutManager = NSLayoutManager()
let textContainer = NSTextContainer(size: size)
textContainer.lineBreakMode = mode
textContainer.maximumNumberOfLines = self.numberOfLines
layoutManager.addTextContainer(textContainer)
textStorage.addLayoutManager(layoutManager)
let range = NSRange(location: 0, length: layoutManager.numberOfGlyphs)
var index = 0
layoutManager.enumerateLineFragments(forGlyphRange: range) { _, _, _, _, stop in
if index >= self.numberOfLines {
stop.pointee = true
}
index += 1
}
return layoutManager.characterRange(forGlyphRange: NSRange(location: 0, length: layoutManager.numberOfGlyphs), actualGlyphRange: nil).length
}
}
마지막으로 익스텐션으로 라벨의 기능을 넣어주면 된다. 동적으로 움직이고 계산해주는 ~~~~
이렇게 하니 속 시원하게 잘 되네.
다음에도 잘 이용해먹자 아자자!