Notice
Recent Posts
Recent Comments
Link
관리 메뉴

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

[iOS - swift] Custom Button 만드는 방법 (커스텀 버튼) 본문

UI 컴포넌트 (swift)

[iOS - swift] Custom Button 만드는 방법 (커스텀 버튼)

jake-kim 2023. 1. 4. 22:14

버튼 아래에 label이 있는 커스텀 버튼

커스텀 버튼 구현 아이디어

  • UIButton을 상속하여 사용
  • hilighted 애니메이션 처리?
    • UIButton에서 제공해주는 isHighlightedsetImage를 오버라이딩하여 사용

커스텀 버튼 구현

  • UI 준비 - stackView하나와 imageView, label 준비
class MyButton: UIButton {
    private let stackView: UIStackView = {
        let view = UIStackView()
        view.axis = .vertical
        view.alignment = .center
        view.distribution = .fill
        view.spacing = 12
        view.isUserInteractionEnabled = false
        view.translatesAutoresizingMaskIntoConstraints = false
        return view
    }()
    private let myImageView: UIImageView = {
        let view = UIImageView()
        view.isUserInteractionEnabled = false
        return view
    }()
    private let label: UILabel = {
        let label = UILabel()
        label.text = "label"
        label.textColor = .black
        label.translatesAutoresizingMaskIntoConstraints = false
        return label
    }()
}
  • 외부 인터페이스인 text, normalImage, highlighed, highlightedImage 프로퍼티 준비
    • isHighlighted 오버라이딩: highlighted 상태가 변경되면 UI 업데이트가 필요하므로, didSet에서 updateStateUI 메소드를 호출
    var text: String? {
        didSet { label.text = text }
    }
    var normalImage: UIImage? {
        didSet { updateStateUI() }
    }
    var highlightedImage: UIImage? {
        didSet { updateStateUI() }
    }
    
    override var isHighlighted: Bool {
        didSet { updateStateUI() }
    }
    
    private func updateStateUI() {
        switch state {
        case .normal:
            label.alpha = 1
            myImageView.image = normalImage
        case .highlighted:
            label.alpha = 0.5
            myImageView.image = highlightedImage
        default:
            break
       }
  • 뷰 초기화
    init() {
        super.init(frame: .zero)
        setUp()
    }
    required init?(coder: NSCoder) {
        fatalError()
    }
    
    private func setUp() {
        addSubview(stackView)
        [myImageView, label].forEach(stackView.addArrangedSubview(_:))

        NSLayoutConstraint.activate([
            stackView.leftAnchor.constraint(equalTo: leftAnchor),
            stackView.rightAnchor.constraint(equalTo: rightAnchor),
            stackView.bottomAnchor.constraint(equalTo: bottomAnchor),
            stackView.topAnchor.constraint(equalTo: topAnchor),
        ])
    }
  • super.setImage(_:for:)를 호출하지 않고 내부 이미지 뷰만 변경하도록 구현
    override func setImage(_ image: UIImage?, for state: UIControl.State) {
//        super.setImage(image, for: state) <- 호출 x
        switch state {
        case .normal:
            normalImage = image
        case .highlighted:
            highlightedImage = image
        default:
            break
        }
    }
  • 사용하는 쪽 
class ViewController: UIViewController {
    private let button: MyButton = {
        let button = MyButton()
        button.normalImage = UIImage(named: "img")
        button.highlightedImage = UIImage(named: "img")?.alpha(0.5)
        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),
        ])
    }
}

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

Comments