티스토리 뷰

UILabel 을 사용하다 보면 글자가 길어짐에 따라 라인이 추가되는데 한정된 영역에서 글자를 어떻게 처리할 지 고민하게 된다.

그러면서 lineBreakMode가 나왔고 애플에서는 가독성을 위해서 글자를 단어 단위로 잘라서 끝쪽에 애매한 부분은 다음 줄 부터 시작하게 됩니다.

일반적인 상황에서는 상관이 없지만

네이버 시리즈의 제목을 표기하는 곳같이 글자를 단어 단위로 짜르게 되면 영역이 상당히 비어 보이는 느낌을 가지게 됩니다.

그래서 문자 단위로 자르기 위해

label.lineBreakMode = .byCharWrapping

으로 변경을 하게 됩니다.

아쉽게도 .byCharWrapping 는 글자가 짤리는 영역에 … 으로 축소해주고 싶지만..

이런식으로 끝에 넘어가도 글자가 …으로 축소 되지않습니다.

label.lineBreakMode = .byTruncatingTail

속성으로 바꾸면 어떻게 표현될까요

“애플부탁드립니다.” 라는 부분이 가독성을 위해 다음 줄로 개행이 된 모습이 보입니다.

지금은 보기 괜찮지만

이렇게 짤려지는 글자가 길어지면 개행을 하면서 빈 공간이 많이 나오게 됩니다.

이러한 해결을 하기 위해서 직접.. 뷰 영역을 계산해서 … 개행을 추가하는 방법이 있다고 합니다. 😢(직접구현 하기)

extension UILabel {
    /// 글자가 numberofLines을 넘어가면 뒤에 ...으로 변경
    func truncTail() {
        guard let text = attributedText, text.length > 0 else { return }

        let range = NSRange(location: text.length - 1, length: 1)
        let lastText = text.attributedSubstring(from: range)
        let addWidth = lastText.size().width // 임의로 끝에 글자 공간 한개 더 넣어서 계산 (dynamicfont 글자 크기 조정할때 계산식이 마지막 끝에 애매하게 걸리면 …이 영역 밖으로 나감
        let maxline = CGFloat(numberOfLines)
        if ((text.size().width + addWidth) / self.frame.size.width) > CGFloat(maxline), numberOfLines != 0 {
            var attributedString = NSMutableAttributedString(attributedString: text)
            var index = attributedString.length
            // 글자 한개씩 짤라서 ...으로 변경
            repeat {
                index -= 1
                attributedString = replaceLastToDot(text: attributedString, index: index)
            } while (attributedString.size().width + addWidth) > self.frame.size.width * CGFloat(maxline)
        attributedText = attributedString
        }
    }

    /// index 부터 마지막 글자까지 ...으로 치환
    func replaceLastToDot(text: NSMutableAttributedString, index: Int) -> NSMutableAttributedString {
        let range =  NSRange(location: index, length: text.length - index)
        text.replaceCharacters(in: range, with: "…")

        return text
    }
}

위 함수를 이용해서 구현을 해보면

import UIKit

class ViewController: UIViewController {

    @IBOutlet weak var testLabel: UILabel!
    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view.

        testLabel.text = "...처리되면서문자단위로짤라주세요 애플부탁드립니다부탁드립니다부탁드립니다부탁드립니다부탁드립니다. 글자채우기글자채우기글자채우기글자채우기글자채우기글자채우기글자채우기글자채우기글자채우기글자채우기글자채우기글자채우기글자채우기글자채우기글자채우기글자채우기글자채우기글자채우기"
        testLabel.lineBreakMode = .byCharWrapping
        testLabel.truncTail()
    }
}

실행 해보면

이전과 다르게 문자 단위로 자르면서 … 줄여지는 효과를 만들 수 있습니다.

이전 글과 합쳐서 사용하면 이미지도 넣으면서 글자를 문자 단위로 줄이는 네이버 시리즈 와 같은 라벨을 생성할 수 있습니다.

import UIKit

class ViewController: UIViewController {

    @IBOutlet weak var testLabel: UILabel!
    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view.

        testLabel.text = "...처리되면서문자단위로짤라주세요 애플부탁드립니다부탁드립니다부탁드립니다부탁드립니다부탁드립니다. 글자채우기글자채우기글자채우기글자채우기글자채우기글자채우기글자채우기글자채우기글자채우기글자채우기글자채우기글자채우기글자채우기글자채우기글자채우기글자채우기글자채우기글자채우기"
        testLabel.lineBreakMode = .byCharWrapping
        let image = UIImage(systemName: "person.fill")
        testLabel.addLeadingImage(image: image)
        testLabel.truncTail()
    }
}

 


위와 같은 식으로 글자도 줄이면서 이미지도 편하게 넣을 수 있습니다.

truncTail() 함수 내부에서 addWidth를 width에 더해서 글자 1개만큼 사이즈를 키워서 계산을 하는데

글자 끝자리가 space 이거나 중간에 걸칠때 글자를 한개 더 지워야되는데 힘들어서 공통적으로 1개를 더 지우는 방식으로 선택했습니다.

 

'UIKit' 카테고리의 다른 글

iOS UIKit - UILabel 앞에 이미지 넣기  (0) 2023.03.05
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2024/09   »
1 2 3 4 5 6 7
8 9 10 11 12 13 14
15 16 17 18 19 20 21
22 23 24 25 26 27 28
29 30
글 보관함