카테고리 없음

[swift] UIButton 커스텀하기

순진이 2022. 2. 19. 21:27

UIButton 참 많이 쓰는 것 중 하나인데, 코드로 작성하다 보니까 같은 모양의 버튼을 만들 때 중복되는 코드가 너무 많은 거에요.

 

그래서 부랴부랴 써보는 UIButton 커스텀하기 입니다!

 

 

우선 평소처럼 UI부터 잡고 갈게요!

반반 배경도 넣어줬구요, 일단 버튼은 UIButton의 객체로 찍어내었습니다!

더보기
class ViewController: UIViewController {

    let topView = UIView()
    let bottomView = UIView()
    let topBtn = UIButton()
    let bottomBtn = UIButton()

    override func viewDidLoad() {
        super.viewDidLoad()
        configureUI()
    }
}

//MARK: -UI
extension ViewController {
    final private func configureUI() {
        setAttributes()
        addTarget()
        setConstraints()
    }
    
    final private func setAttributes() {
        topView.backgroundColor = MyColor.greenColor
        bottomView.backgroundColor = MyColor.grayColor
        
    }
    
    final private func addTarget() {
        topBtn.addTarget(self, action: #selector(topBtnTapped(_:)), for: .touchUpInside)
        bottomBtn.addTarget(self, action: #selector(bottomBtnTapped(_:)), for: .touchUpInside)
    }
    
    final private func setConstraints() {
        let stackView = UIStackView(arrangedSubviews: [topView, bottomView])
        stackView.axis = .vertical
        stackView.distribution = .fillEqually
        
        let stackBtn = UIStackView(arrangedSubviews: [topBtn, bottomBtn])
        stackBtn.axis = .vertical
        stackBtn.distribution = .fillEqually
        stackBtn.spacing = 350
        
        [stackView, stackBtn].forEach {
            view.addSubview($0)
            $0.translatesAutoresizingMaskIntoConstraints = false
        }
        
        NSLayoutConstraint.activate([
            stackView.leadingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.leadingAnchor),
            stackView.topAnchor.constraint(equalTo: view.topAnchor),
            stackView.trailingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.trailingAnchor),
            stackView.bottomAnchor.constraint(equalTo: view.bottomAnchor),
            
            stackBtn.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor, constant: 160),
            stackBtn.centerXAnchor.constraint(equalTo: view.safeAreaLayoutGuide.centerXAnchor),
            
            topBtn.widthAnchor.constraint(equalToConstant: 130)
        ])
    }
}

자 이제 커스텀 버튼을 만들어 볼게요!!

해당 프로젝트를 선택 후 오른쪽 버튼을 눌러서 New File을 해주거나 Command+N을 눌러 파일을 추가하세요!

그 후에는 Swift.file을 선택한 후, 파일 이름을 MyButton.swift로 설정해볼게요!

 

그리고는 UIButton을 상속받는 클래스를 하나 만들어줍니다.

import UIKit

class MyButton: UIButton {  

}

 

UIButton 클래스를 상속받기 때문에 상위 클래스의 생성자를 호출해주어야 해욧

import UIKit

class MyButton: UIButton {
    override init(frame: CGRect) {
        super.init(frame: frame)
    }
    
}

 

필수생성자도 구현을 해줍니다. (빨간 에러가 알아서 알랴줌)

필수생성자는 말 그대로 반드시 하위에서 구현해야 하는 생성자인데요, 원래는 자동상속되지만, 하위 클래스에 지정생성자가 있는 경우에는 선언을 해줘야 합니당. 그래서 에러가 뜨더라구용.

 

 

이제 제가 원하는 버튼의 생성자를 만들어줄게요.

저는 MyButton을 찍어낼 때, title을 가지고 찍어내려고 해요. 그래서 String타입의 title 파라미터를 받는 생성자를 만듭니당.

 

그리고 이 생성자도 상위 생성자를 호출해주도록 합니다.

import UIKit

class MyButton: UIButton {
	//상위 클래스의 생성자 재정의
    override init(frame: CGRect) {
        super.init(frame: frame)
    }
    
    //MyButton 클래스만의 생성자 생성
    init(title: String) {
        super.init(frame: .zero)
    }
    
    //필수 생성자 구현
    required init?(coder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
}

 

이제는 다 끝났어요!

이제 MyButton만의 생성자를 생성한 곳에 원하는 버튼의 설정만 해주면 됩니다!

import UIKit

class MyButton: UIButton {
    override init(frame: CGRect) {
        super.init(frame: frame)
    }
    
    init(title: String) {
        super.init(frame: .zero)
        setTitle(title, for: .normal) // 버튼의 타이틀 설정
        titleLabel?.font = UIFont(name: "SongMyung-Regular", size: 60) // 폰트 설정
        backgroundColor = UIColor.white // 버튼 배경 설정
        setTitleColor(.darkGray, for: .normal) // 타이틀 컬러 설정
        layer.cornerRadius = 20 // 테두리 곡률 설정
        layer.borderWidth = 2 // 테두리 두께 설정
        layer.shadowColor = UIColor.darkGray.cgColor // 테두리 컬러 설정
    }
    
    required init?(coder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
}

 

만약에 사이즈까지 다르게 해주고 싶다면, title과 마찬가지로 size파라미터를 하나 설정해주면 되겠져?

아래처럼 말이져!

    init(title: String, size: CGFloat) {
        super.init(frame: .zero)
        setTitle(title, for: .normal) // 버튼의 타이틀 설정
        titleLabel?.font = UIFont(name: "SongMyung-Regular", size: size) // 폰트 설정
        backgroundColor = UIColor.white // 버튼 배경 설정
        setTitleColor(.darkGray, for: .normal) // 타이틀 컬러 설정
        layer.cornerRadius = 20 // 테두리 곡률 설정
        layer.borderWidth = 2 // 테두리 두께 설정
        layer.shadowColor = UIColor.darkGray.cgColor // 테두리 컬러 설정
    }

 

이제 다시 viewDidLoad 위로 갑니다.

아까는 임시로 UIButton의 객체로 만들었었는데요, MyButton의 객체로 바꿔볼게요.

class ViewController: UIViewController {

    let topView = UIView()
    let bottomView = UIView()
    let topBtn = MyButton(title: "순진")
    let bottomBtn = MyButton(title: "버튼")

    override func viewDidLoad() {
        super.viewDidLoad()
        configureUI()
    }
}

 

MyButton을 치고 자동완성되는 항목을 보면 제가 만든 MyButton클래스와 그 생성자가 보이져?

저 생성자를 이용해주면 됩니다!!

그럼 아래처럼 이제 MyButton의 객체를 타이틀만 다르게 해서 계속 찍어낼 수 있고, 다른 뷰컨에서도 계속 사용할 수 있게되기 때문에 넘나 편하겠져? 


오늘도 틀린 게 있으면 많이 알려주십셔!! 슨배님덜