iOS/StoryBoard

조건문을 이용해서 백그라운드 색상 변경하기

소재훈 2022. 2. 17. 20:18

구현하고자 하는 기능은 위와 같이 로그인 버튼을 눌렀을 때 메인화면으로 이동하고, 버튼을 눌러서 배경색을 변경시키는 것이다.

 

주요 기능은 조건문을 이용해서 색상을 변경시키는 것이지만, ViewController를 직접 코드로만 작성해보고, Label과 Button을 추가시키는 것까지 함께 해보자

 

먼저 화면 충앙에 "메인 화면"을 추가하고 중앙에 위치시켜보자.

var titleLabel: UILabel = {
    let label = UILabel()
    label.text = "메인화면"
    label.textAlignment = .center
    label.font = UIFont.boldSystemFont(ofSize: 50)
    label.textColor = .white
    return label
}()

label의 텍스트와, 기본적인 설정

정렬, 폰트, 폰트의 굵기, 색상들을 설정해준다.

 

버튼의 속성은 다음과 같다.

let changeButton: UIButton = {
    let button: UIButton = UIButton(type: .system)
    button.setTitle("배경색 바꾸기", for: .normal)
    button.setTitleColor(.black, for: .normal)
    button.titleLabel?.font = UIFont.boldSystemFont(ofSize: 20)
    button.backgroundColor = UIColor.white
    button.layer.cornerRadius = 5
    button.contentEdgeInsets = UIEdgeInsets(top: 5, left: 20, bottom: 5, right: 20)
    button.addTarget(self, action: #selector(changeBg), for: .touchUpInside)

    return button
}()

버튼의 타입을 system으로 설정해 주었다. UIButton 에는 6가지의 타입이 있고, 각 타입의 역할은 이곳 을 참고하자. system은 스토리보드에서 버튼을 추가했을 때 나타나는 디폴트 타입이다.

타이틀, 타이틀의 색상을 지정

폰트의 사이즈, 백그라운드 색상

그리고 버튼에 둥근 모서리를 주기 위해서 layer.cornerRadius 값을 주었다.

이 상태에서 버튼을 출력하게 되면, 텍스트와 버튼이 딱맞도록 출력된다.

contentEdgeInsets 옵션에서 UIEdgeInset(top:left:bottom:right:)를 사용해서 상하좌우의 패딩(Padding)을 줄 수 있다.

하지만 이 코드를 작성하니 경고가 발생하더라...

contentDegeInsets는 iOS 15.0에서는 중요하지 않아... UIButtonConfiguration을 사용하면 무시된다고한다..ㅠ

 

버튼이 눌렸을 때의 액션은 addTarget를 사용해 등록해준다. 버튼을 사용하는 ViewController는 자기 자신이니 

첫번째 인자로는 self를, 

두번째 인자인 action에는 동작할 메서드를 등록해준다. #selector는 Objective-C에서 온 개념이기 때문에 @objc가 앞에 붙은 메서드로 등록해 주어야 한다.

세번째 인자로는 어느 동작이 나타날 때 메서드가 수행되느냐 이다. 여기서는 버튼을 눌렀다 뗐을 때인 touchUpInside를 선택해주었다.

 

 

화면이 출력되기 직전에 Label과 백그라운드 색상을 설정해야 하므로 viewDidLoad함수에서 작업한다.

override func viewDidLoad() {
    super.viewDidLoad()

    isBGOrange = true

    view.backgroundColor = UIColor.systemOrange
    view.addSubview(titleLabel) //서브뷰에 먼저등록을 해야한다.

    titleLabel.translatesAutoresizingMaskIntoConstraints = false
    titleLabel.centerYAnchor.constraint(equalTo: view.centerYAnchor).isActive = true// 상위에 있는 중간으로 Y앵커를 두겠다.
    titleLabel.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true// 상위에 있는 중간으로 X앵커를 두겠다.

    view.addSubview(changeButton)
    changeButton.translatesAutoresizingMaskIntoConstraints = false
    changeButton.topAnchor.constraint(equalTo: titleLabel.bottomAnchor, constant: 20).isActive = true
    changeButton.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true
}

백그라운드 컬러를 System Orange Color로 만들고, 

Label을 뷰에 나타내기 위해서는 addSubView 메서드를 사용하여 서브뷰에 먼저등록을 해야함에 주의하자.

Label을 정가운데 위치시키기 위해서, centerXAnchor, centerYAnchor를 걸어주는데

반드시!!! 서브뷰에 등록시켜준 후에 constraint를 추가시켜 주어야 함에 주의하자.

 

그런데, Label과 Button의 constraint를 추가해 주기 이전에 

translatesAutoresizingMaskIntoConstraints라는 프로퍼티를 false로 설정해 주는 것을 볼 수 있다.

이것이 무엇일까 궁금했는데 Zedd님의 블로그를 보고 공부할 수 있었다.

 

iOS ) translatesAutoresizingMaskIntoConstraints

안녕하세요 :) Zedd입니다. 오늘은...! translatesAutoresizingMaskIntoConstraints..!을 정확히 알아보는 공부~.~ translatesAutoresizingMaskIntoConstraints 사실 엄청 많이 보셨을 코드에요. self.view.trans..

zeddios.tistory.com

내용을 요약하면 

 trainslatesAutoresizingMaskIntoConstraints의 값이 true이면, 시스템은 autoresizing mask의 값을 보고 지정된 행동(behavior)를 복제하는 Constraint집합을 만든다고 한다.

그리고 View의 frame, bound, center 프로퍼티를 사용해서 View의 크기와 위치를 수정해서 auto layout에서 정적인 프레임 기반  레이아웃을 만들 수 있다. 이렇게 autoresizing mask constraint는 view의 크기와 위치를 완전히 지정한다.

따라서 지금처럼 요소의 크기, 위치를 수정하기 위해서 constraint를 추가할 수 없고, auto layout을 사용해서 View의 크기와 위츠를 동적으로 계산하려면, 이 프로퍼티를 false로 설정하고, view에 모호하지 않고, 충돌하지 않는 constraint집합을 제공해야 한다.

기본적으로 지금처럼 프로그래밍 방식으로 만드는 모든 View에 대해서 이 프로퍼티는 true로 설정된다. 스토리보드에서 View를 추가할 때 이 프로퍼티의 값은 false로 자동설정된다. 

따라서 우리는 지금 프로그래밍 방식으로 View를 만들었기 때문에, 우리가 원하는 constraint를 추가하기 위해서는 프로퍼티의 값을 false로 바꿔주어야 한다는 것이다.

 

이제 버튼을 눌렀을 때의 동작인 changeBG함수만 조건문을 정의해주면 된다.

사실 함수를 작성하는 것 자체는 굉장히 간단하다!!

//배경색을 바꾼다.
@objc fileprivate func changeBg() {
    print("MainViewController - changeBg() called")

    if isBGOrange == true {
        //
        view.backgroundColor = UIColor.systemYellow
        isBGOrange = false
    } else {
        //
        view.backgroundColor = UIColor.systemOrange
        isBGOrange = true
    }
}

@objc 가 붙은 이유는 위에서 설명하였고, 이 클래스에서만 사용할 함수이기 때문에 fileprivate 접근수준을 지정해주었다.

현재 상태에 따라서 색상을 바꾸어준다.

현재 오렌지라면 노란색으로...노란색이라면 오랜지 색으로...

간단하게 구현해 줄 수 있다.