Notice
Recent Posts
Recent Comments
Link
관리 메뉴

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

[iOS - swift] UIButton에 텍스트가 있는 버튼 구현 방법 (imageEdgeInsets, titleEdgeInsets, contentEdgeInsets) 본문

UI 컴포넌트 (swift)

[iOS - swift] UIButton에 텍스트가 있는 버튼 구현 방법 (imageEdgeInsets, titleEdgeInsets, contentEdgeInsets)

jake-kim 2023. 2. 1. 22:55

UI 구현 시 주의할 점

  • 최대한 constraint를 적게하고, UIKit에서 기본적으로 주어진 프로퍼티들을 이용하여 최대한 단순하게 만드는 것
    • constraint를 적게하는 이유: Commit Hitches가 줄어들어 UI 성능에 도움 (관련 글은 이전 포스팅 글 참고
    • 추가적인 뷰 없이 내부적으로 있는 proprety를 이용하여 구현하면 뷰의 복잡도가 줄기 때문에 장황하지 않고 단순하게 구현이 가능

UIButton에 텍스트가 있는 버튼

UIButton 하나로 만든 UI

  • 위 UI는 UIButton한개로만 구현
    • 다른 방법은, UIStackView + UIImageView + UILabel로 만들 수도 있지만 코드가 장황해지고, 타이틀을 눌렀을 때도 터치 반응을 해야하므로 gesture도 따로 등록해줘야 하는 번거로움이 있으므로 UIButton하나로만 할 것

구현 방법

  • UIButton에서 setTitle, setImage를 설정하는 것은 자주 있으므로 쉽지만, inset 설정이 핵심
class ViewController: UIViewController {
    private let button: UIButton = {
        let button = UIButton()
        
        // text
        // TODO
        
        // image
        // TODO
        
        // inset
        // TODO
        
        button.backgroundColor = .lightGray.withAlphaComponent(0.3)
        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),
        ])
    }
}
  • 버튼의 text는 titleLabel로 label의 속성을 정하고, setTitle로 text입력
// text
button.titleLabel?.font = .systemFont(ofSize: 16)
button.setTitle("타이틀", for: .normal)
button.setTitleColor(.systemBlue, for: .normal)
button.setTitleColor(.blue, for: .highlighted)
  • 버튼의 이미지는 setImage 사용
// image
button.setImage(UIImage(systemName: "person.crop.circle"), for: .normal)
button.setImage(UIImage(systemName: "person.crop.circle.fill"), for: .highlighted)
  • 핵심부분인, 이미지와 텍스트 사이의 spacing을 부여하는 부분 (아래에서 계속)
before after

UIButton 한개로만 만든 UI

UIButton의 inset

(iOS 15에서부턴 deprecated)

  • imageEdgeInsets: 이미지의 inset을 의미
    • 회색 영역에서 벗어난 image를 눌러도 버튼 touch 이벤트 x
button.imageEdgeInsets = .init(top: 0, left: -100, bottom: 0, right: 0)

imageEdgeInsets.left: -100

  • titleEdgeInsets: 타이틀의 inset을 의미
    • 회색 영역에서 벗어난 text를 눌러도 버튼 touch 이벤트 x
button.titleEdgeInsets = .init(top: 0, left: 0, bottom: 0, right: -100)

titleEdgeInsets.right = -100

  • contentEdgeInsets
    • 크기를 늘려주며, 늘어난 부분을 클릭하면 touch 이벤트 반응 o
button.contentEdgeInsets = .init(top: 0, left: 100, bottom: 0, right: 0)

contentEdgeInsets.left = 100

  • imageEdgeInsets, titleEdgeInsets, contentEdgeInsets의 핵심?
    • UIButton의 크기를 늘리는 프로퍼티는 contentEdgeInsets만 해당

inset을 이용하여 이미지와 타이틀의 간격 주기

(이미지와 타이틀의 간격을 6으로 주고 싶은 경우)

let intervalSpacing = 6.0
let halfIntervalSpacing = intervalSpacing / 2
  • 1. contentEdgeInset으로 공간 넓히기
button.contentEdgeInsets = .init(top: 0, left: halfIntervalSpacing, bottom: 0, right: halfIntervalSpacing)
  • 2. 이미지를 왼쪽으로 3만큼 당기기
button.imageEdgeInsets = .init(top: 0, left: -halfIntervalSpacing, bottom: 0, right: halfIntervalSpacing)
  • 3. 텍스트를 오른쪽으로 3만큼 당기기
button.titleEdgeInsets = .init(top: 0, left: halfIntervalSpacing, bottom: 0, right: -halfIntervalSpacing)

(inset부분 전체 코드)

// inset
let intervalSpacing = 6.0
let halfIntervalSpacing = intervalSpacing / 2
button.contentEdgeInsets = .init(top: 0, left: halfIntervalSpacing, bottom: 0, right: halfIntervalSpacing)
button.imageEdgeInsets = .init(top: 0, left: -halfIntervalSpacing, bottom: 0, right: halfIntervalSpacing)
button.titleEdgeInsets = .init(top: 0, left: halfIntervalSpacing, bottom: 0, right: -halfIntervalSpacing)

완성

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

* 참고

https://developer.apple.com/documentation/uikit/uibutton/1624034-imageedgeinsets

https://developer.apple.com/documentation/uikit/uibutton/1624010-titleedgeinsets

https://developer.apple.com/documentation/uikit/uibutton/1624036-contentedgeinsets

Comments