관리 메뉴

김종권의 iOS 앱 개발 알아가기

[iOS - swift] UIButton 안의 UILabel, UIImageView 사용하면 안되는 이유 (볼드체 텍스트 활성화 문제, system font) 본문

iOS 응용 (swift)

[iOS - swift] UIButton 안의 UILabel, UIImageView 사용하면 안되는 이유 (볼드체 텍스트 활성화 문제, system font)

jake-kim 2023. 4. 20. 01:05

UIButton 안의 UIImageView, UILabel 사용 시 주의사항

* UIButton하나로 UIButton, UILabel의 inset 다루는 방법은 이전 포스팅 글 참고

  • 시스템 설정에서 볼드체 텍스트 활성화 할 경우 글자가 잘리는 이슈

일반적인 경우 볼드체 텍스트 활성화한 경우

  • 볼드체 텍스트 활성화
    • 왼쪽의 UIImageView가 오른쪽으로 이동하고 오른쪽의 UILabel도 왼쪽으로 이동한 상황
    • 즉 inset 값들이 초기화된 상황

볼트체 활성화 시 발생되는 문제: titleLabel이 잘림

  • 현재까지 전체 코드
import UIKit

class ViewController: UIViewController {
    private let button: RoundableButton = {
        let button = RoundableButton()
        
        // title
        button.setTitle("버튼", for: .normal)
        button.setTitleColor(.white, for: .normal)
        
        // image
        let image = UIImage(named: "blog")?.imageWith(newSize: .init(width: 30, height: 30))
        button.setImage(image, for: .normal)
        
        // inset
        let verticalSpace = 4.0
        let horizontalSpace = 12.0
        let interSpace = 3.0
        button.contentEdgeInsets = .init(top: verticalSpace, left: horizontalSpace, bottom: verticalSpace, right: horizontalSpace)
        button.imageEdgeInsets = .init(top: 0, left: -interSpace, bottom: 0, right: interSpace)
        button.titleEdgeInsets = .init(top: 0, left: interSpace, bottom: 0, right: -interSpace)
        
        button.backgroundColor = .lightGray
        button.layer.borderColor = UIColor.lightGray.cgColor
        button.layer.borderWidth = 1
        
        button.translatesAutoresizingMaskIntoConstraints = false
        return button
    }()
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        view.addSubview(button)
        NSLayoutConstraint.activate([
            button.centerYAnchor.constraint(equalTo: view.centerYAnchor),
            button.centerXAnchor.constraint(equalTo: view.centerXAnchor),
        ])
    }
    
}

extension UIImage {
    func imageWith(newSize: CGSize) -> UIImage {
        let image = UIGraphicsImageRenderer(size: newSize).image { _ in
            draw(in: CGRect(origin: .zero, size: newSize))
        }
        return image.withRenderingMode(renderingMode)
    }
}

final class RoundableButton: UIButton {
    override func layoutSubviews() {
        super.layoutSubviews()
        layer.cornerRadius = frame.size.height / 2
    }
}

볼드체 텍스트 활성화 시 발생하는 문제

  • 볼드체를 활성화하면 UIButton안의 UIImageView, UILabel에 벌어지는 현상
    •  레이아웃이 반영된 후 frame을 알기위해서 viewDidLayoutSubviews 메소드에서 UIImageView, UILabel의 frame을 찍어봐서 확인
    • 각각 print(button.imageView?.frame), print(button.titleLabel?.frame)로 확인
    • (x, y, width, height) 값을 확인
  일반적인 경우 볼드체 텍스트 활성화
UIButton.imageView (9.0, 4.0, 30.0, 30.0) (16.0, 4.0, 31.0, 30.0)
UIButton.titleLabel (45.0, 8.0, 32.0, 22.0) (53.6, 8.0, 16.0, 22.0)
  • 볼드체를 활성화하면 x좌표가 변경되어서 titleLabel도 잘리는 것
    • imageView의 경우 x좌표가 +7
    • titleLabel의 경우 x좌표가 +8.6
  • titleLabel은 system font이므로, bold 체로 설정하면 폰트도 semi bold로 변경됨
  일반적인 경우 볼드체 텍스트 활성화
button.titleLabel?.font <UICTFont: 0x119f0ce90> font-family: ".SFUI-Regular"; font-weight: normal; font-style: normal; font-size: 18.00pt <UICTFont: 0x105409610> font-family: ".SFUI-Semibold"; font-weight: normal; font-style: normal; font-size: 18.00pt

해결 방법

  • 가장 좋은 방법은 UIButton의 UIImageView와 UILabel을 사용하지 않고 직접 Custom View를 만들어서 사용할 것
    • viewDidLayoutSubviews에서 frame값과 font값을 설정해도 시스템에서 설정한 우선순위가 높으므로, 다 무시됨
  • UILabel의 adjustsFontSizeToFitWidth를 true로하여 UILabel이 잘리지 않게 하는 방법
일반적인 경우 볼드체 텍스트 활성화한 경우

* 전체 코드: https://github.com/JK0369/ExCustomButton_bold

Comments