본문 바로가기

Project/FirebaseTest

FireBase - 커스텀 버튼, 뷰, 텍스트 필드에 대해

코드를 구현하다 보면, 동일하게 반복되는 코드가 있습니다. 

오늘은 이런 코드를 어떤 식으로 구현하면 좋을지에 대해 배웠습니다. 

 

이전까지는 버튼을 예로 들면, 버튼의 외형은 동일하나, 그 안에 들어가는 텍스트의 크기나 굵기가 다를 경우가 있었어도, 이에 대해 대체할 방법에 잘 알지 못했습니다. 

 

오늘은 몇 가지에 대해 알아보려고 합니다.

 

AuthHeaderView

import UIKit

class AuthHeaderView: UIView {
    
    // MARK: - UI Components
    private let imageView: UIImageView = {
        let imageView = UIImageView()
        imageView.contentMode = .scaleAspectFit
        imageView.image = UIImage(named: "logonew")
        imageView.layer.cornerRadius = 45
        imageView.clipsToBounds = true
        return imageView
    }()
    
    private let titleLabel: UILabel = {
        let label = UILabel()
        label.textColor = .label
        label.textAlignment = .center
        label.font = .systemFont(ofSize: 26, weight: .bold)
        label.text = "ERROR"
        return label
    }()
    
    private let subTitleLabel: UILabel = {
        let label = UILabel()
        label.textColor = .label
        label.textAlignment = .center
        label.font = .systemFont(ofSize: 16, weight: .regular)
        label.text = "ERROR"
        return label
    }()
    
    
    // MARK: - Life Cycle
    init(title: String, subTitle: String) {
        super.init(frame: .zero)
        self.titleLabel.text = title
        self.subTitleLabel.text = subTitle
        
        configureConstraints()
    }
    
    required init?(coder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
    
    // MARK: - Constraints
    private func configureConstraints() {
        
        self.addSubview(imageView)
        self.addSubview(titleLabel)
        self.addSubview(subTitleLabel)
        
        imageView.translatesAutoresizingMaskIntoConstraints = false
        titleLabel.translatesAutoresizingMaskIntoConstraints = false
        subTitleLabel.translatesAutoresizingMaskIntoConstraints = false
        
        NSLayoutConstraint.activate([
            
            self.imageView.topAnchor.constraint(equalTo: self.topAnchor, constant: 30),
            self.imageView.centerXAnchor.constraint(equalTo: self.centerXAnchor),
            self.imageView.widthAnchor.constraint(equalToConstant: 90),
            self.imageView.heightAnchor.constraint(equalTo: imageView.widthAnchor),
            
            self.titleLabel.topAnchor.constraint(equalTo: imageView.bottomAnchor, constant: 19),
            self.titleLabel.leadingAnchor.constraint(equalTo: self.leadingAnchor),
            self.titleLabel.trailingAnchor.constraint(equalTo: self.trailingAnchor),
            
            self.subTitleLabel.topAnchor.constraint(equalTo: titleLabel.bottomAnchor, constant: 12),
            self.subTitleLabel.leadingAnchor.constraint(equalTo: self.leadingAnchor),
            self.subTitleLabel.trailingAnchor.constraint(equalTo: self.trailingAnchor)
            
        ])
    }
    
}

 

위의 코드는 iOS 앱 개발을 위한 UIKit 프레임워크를 사용하여 AuthHeaderView라는 커스텀 뷰를 구현한 코드입니다. 이 뷰는 사용자 인증 화면에 적합한 헤더를 제공하며 이미지, 제목, 및 부제목을 포함하고 있습니다.

 

주요 구성 요소 설명

1. 클래스 구조

  • AuthHeaderView는 UIView를 상속받아 커스텀 뷰로 제작되었습니다.
  • 이 뷰는 크게 3가지 UI 컴포넌트(UIImageView, UILabel, UILabel)로 구성되어 있습니다.

2. UI Components

  1. imageView:
    • 타입: UIImageView
    • 역할: 헤더에서 로고나 이미지를 표시합니다.
    • 설정:
      • contentMode: 이미지를 비율에 맞게 축소/확대하여 맞춥니다(.scaleAspectFit).
      • layer.cornerRadius: 둥근 모서리를 위해 반지름 값을 45로 설정했습니다.
      • clipsToBounds: 코너의 반경 설정이 적용되도록 클리핑합니다.
  2. titleLabel:
    • 타입: UILabel
    • 역할: 헤더의 주요 제목을 표시합니다.
    • 설정:
      • 색상: UIColor.label (다크모드/라이트모드 호환 가능)
      • 폰트: 굵고 큰 텍스트 (.systemFont(ofSize: 26, weight: .bold)).
  3. subTitleLabel:
    • 타입: UILabel
    • 역할: 제목 아래 부제목을 표시합니다.
    • 설정:
      • 폰트: 상대적으로 작은 크기의 일반 텍스트 (.systemFont(ofSize: 16, weight: .regular)).

3. 생성자

  • init(title: String, subTitle: String):
    • 초기화 시 제목(title)과 부제목(subTitle) 텍스트를 설정합니다.
    • super.init(frame: .zero)를 호출하여 부모 클래스 초기화.
  • required init?(coder: NSCoder):
    • 인터페이스 빌더에서 사용할 경우 미리 구현되도록 fatalError 처리. 이 뷰는 코드로만 사용하도록 설계된 것 같습니다.

 

4. 레이아웃 설정

configureConstraints() 메서드는 Auto Layout을 사용하여 뷰 내부 컴포넌트들의 위치와 크기를 설정합니다.

  1. imageView:
    • 상단 여백: self.topAnchor로부터 30pt 간격.
    • 수평 중앙: self.centerXAnchor와 정렬.
    • 너비: 90pt, 높이는 너비와 같음(정사각형).
  2. titleLabel:
    • imageView 아래: imageView.bottomAnchor로부터 19pt 간격.
    • 양쪽 여백: self.leadingAnchor, self.trailingAnchor와 같음.
  3. subTitleLabel:
    • titleLabel 아래: titleLabel.bottomAnchor로부터 12pt 간격.
    • 양쪽 여백: self.leadingAnchor, self.trailingAnchor와 같음.

 

 

코드 요약

AuthHeaderView는 다음과 같은 구조의 헤더를 만드는 데 사용됩니다:

  • 상단에 둥근 이미지를 표시
  • 중간에 큰 제목(titleLabel) 텍스트 표시
  • 아래에 작은 부제목(subTitleLabel) 텍스트 표시
  • 레이아웃은 Auto Layout을 통해 모든 디바이스에서 적절히 동작하도록 설계됨.

 

활용 방법

여기서는 LoginController에서 사용되었습니다.

class LoginController: UIViewController {

    // MARK: - UI Components
    private let headerView = AuthHeaderView(title: "Sign In", subTitle: "Sign in to your account")
    ...

 

 

 

CustomTextField

import UIKit

class CustomTextField: UITextField {

    // MARK: - Enum
    enum CustomTextFieldType {
        case username
        case email
        case password
    }
    
    private let authFieldType: CustomTextFieldType
    
    
    init(fieldType: CustomTextFieldType) {
        self.authFieldType = fieldType
        super.init(frame: .zero)
        
        self.backgroundColor = .secondarySystemBackground
        self.layer.cornerRadius = 10
        
        self.returnKeyType = .done
        self.autocorrectionType = .no
        self.autocapitalizationType = .none
        
        self.leftViewMode = .always
        self.leftView = UIView(frame: CGRect(x: 0, y: 0, width: 12, height: self.frame.size.height))
        
        switch fieldType {
        case .username:
            self.placeholder = "Username"
        case .email:
            self.placeholder = "Email"
            self.keyboardType = .emailAddress
            self.textContentType = .emailAddress
        case .password:
            self.placeholder = "Password"
            self.textContentType = .oneTimeCode
            self.isSecureTextEntry = true 
        }
    }
    
    required init?(coder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
    
}

 

위 코드는 UIKit을 활용하여 CustomTextField라는 커스텀 텍스트 필드를 구현한 코드입니다. 이 텍스트 필드는 사용자 인증과 관련된 필드(username, email, password)를 간편하게 생성하고 관리할 수 있도록 설계되었습니다.


주요 구성 요소 설명

1. 클래스 구조

  • CustomTextField는 UITextField를 상속받아 사용자 정의 기능을 추가한 커스텀 텍스트 필드입니다.
  • 필드의 종류에 따라 동작과 스타일이 다르게 설정됩니다.

 

 

2. 열거형 (Enum)

enum CustomTextFieldType {
    case username
    case email
    case password
}
  • 목적: 텍스트 필드의 종류를 정의합니다.
  • 세 가지 타입이 있습니다:
    • .username: 사용자 이름 입력용.
    • .email: 이메일 주소 입력용.
    • .password: 비밀번호 입력용.

 

3. 프로퍼티

  1. authFieldType (Private):
    • 타입: CustomTextFieldType
    • 텍스트 필드의 타입을 저장합니다.
    • init 메서드에서 초기화되며, 타입에 따라 필드의 특성이 달라집니다.

 

4. 생성자

init(fieldType: CustomTextFieldType)
  • 텍스트 필드의 타입(fieldType)을 지정받아 초기화합니다.
  • 설정 내용:
    1. 공통 설정:
      • backgroundColor: .secondarySystemBackground로 설정하여 배경색을 라이트/다크 모드에 맞게 조정.
      • layer.cornerRadius: 모서리를 둥글게 설정 (반지름: 10).
      • 키보드/자동완성 관련 설정:
        • returnKeyType: .done로 설정하여 키보드에 "완료" 버튼 표시.
        • autocorrectionType: .no로 설정하여 자동 수정 비활성화.
        • autocapitalizationType: .none로 설정하여 첫 글자 자동 대문자 비활성화.
      • 왼쪽 여백 추가:
        • leftViewMode: .always로 설정하여 항상 왼쪽 여백을 유지.
        • leftView: 너비 12pt의 UIView로 여백 공간 추가.
    2. 타입별 설정:
      • .username:
        • 플레이스홀더: "Username".
      • .email:
        • 플레이스홀더: "Email".
        • 키보드 타입: keyboardType = .emailAddress로 이메일 입력에 적합한 키보드 사용.
        • 텍스트 타입: textContentType = .emailAddress로 자동완성을 지원.
      • .password:
        • 플레이스홀더: "Password".
        • 텍스트 타입: textContentType = .oneTimeCode로 비밀번호 자동 입력 지원.
        • 보안 입력: isSecureTextEntry = true로 비밀번호를 가려서 표시.

 

5. 필수 생성자

required init?(coder: NSCoder) {
    fatalError("init(coder:) has not been implemented")
}
  • 인터페이스 빌더 사용을 방지합니다. 이 뷰는 코드로만 사용 가능하도록 설계되었습니다.

 

 

코드 요약

CustomTextField는 사용자 인증 UI에서 자주 사용되는 입력 필드들을 효과적으로 관리할 수 있도록 설계된 커스텀 텍스트 필드입니다.

 

활용 방법

let usernameField = CustomTextField(fieldType: .username)
let emailField = CustomTextField(fieldType: .email)
let passwordField = CustomTextField(fieldType: .password)

// 예시: 부모 뷰에 추가
view.addSubview(usernameField)
view.addSubview(emailField)
view.addSubview(passwordField)

// Auto Layout 설정 예시
usernameField.translatesAutoresizingMaskIntoConstraints = false
NSLayoutConstraint.activate([
    usernameField.topAnchor.constraint(equalTo: view.topAnchor, constant: 50),
    usernameField.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: 20),
    usernameField.trailingAnchor.constraint(equalTo: view.trailingAnchor, constant: -20),
    usernameField.heightAnchor.constraint(equalToConstant: 50)
])

장점

  1. 재사용성: 필드 타입에 따라 설정이 자동으로 적용되어 코드를 간결하게 유지.
  2. 유지보수성: 텍스트 필드 관련 설정을 한 곳에서 관리 가능.
  3. 가독성: 필드 타입을 명확히 구분해 코드 읽기가 쉽습니다.

 

 

CustomButton

import UIKit

class CustomButton: UIButton {
    
    // MARK: Enum
    enum FontSize {
        case big
        case med
        case small
    }
    
    // MARK: - Life Cycle
    init(title: String, hasBackground: Bool = false, fontSize: FontSize) {
        super.init(frame: .zero)
        self.setTitle(title, for: .normal)
        self.layer.cornerRadius = 12
        self.layer.masksToBounds = true
        
        self.backgroundColor = hasBackground ? .systemBlue : .clear
        
        let titleColor: UIColor = hasBackground ? .white : .systemBlue
        self.setTitleColor(titleColor, for: .normal)
        
        switch fontSize {
        case .big:
            self.titleLabel?.font = .systemFont(ofSize: 22, weight: .bold)
        case .med:
            self.titleLabel?.font = .systemFont(ofSize: 18, weight: .semibold)
        case .small:
            self.titleLabel?.font = .systemFont(ofSize: 16, weight: .regular)
        }
        
    }
    
    required init?(coder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
}

 

위 코드는 UIKit을 사용하여 CustomButton이라는 커스텀 버튼을 구현한 코드입니다. 이 버튼은 제목, 배경 색상, 그리고 폰트 크기를 쉽게 설정할 수 있도록 설계되었습니다.

 

주요 구성 요소 설명

1. 클래스 구조

  • CustomButton은 UIButton을 상속받아 특정한 설정을 간단히 적용할 수 있는 커스텀 버튼입니다.

2. 열거형 (Enum)

enum FontSize {
    case big
    case med
    case small
}
  • 목적: 버튼 텍스트의 폰트 크기를 관리합니다.
  • 세 가지 옵션:
    • .big: 큰 폰트 (22pt, 굵은 글씨).
    • .med: 중간 폰트 (18pt, 반굵은 글씨).
    • .small: 작은 폰트 (16pt, 기본 굵기).

3. 생성자

init(title: String, hasBackground: Bool = false, fontSize: FontSize)
  • 버튼의 제목, 배경 색상 유무, 폰트 크기를 설정합니다.
  • 매개변수:
    • title: 버튼에 표시될 텍스트.
    • hasBackground: 버튼의 배경 색상을 설정 (true이면 배경색이 파란색, false이면 투명).
    • fontSize: 텍스트의 폰트 크기(FontSize 열거형 사용).

 

4. 설정 내용

  1. 공통 설정:
    • setTitle: 버튼 텍스트를 설정.
    • layer.cornerRadius: 버튼의 모서리를 둥글게 설정 (반지름: 12).
    • layer.masksToBounds: 뷰의 경계를 넘는 하위 콘텐츠를 잘라냄.
  2. 배경 색상:
    • hasBackground가 true일 경우:
      • 배경색: systemBlue (시스템 파란색).
      • 텍스트 색상: 흰색.
    • hasBackground가 false일 경우:
      • 배경색: 투명 (.clear).
      • 텍스트 색상: 파란색 (systemBlue).
  3. 폰트 크기:
    • fontSize의 값에 따라 버튼 텍스트의 크기와 굵기가 설정됩니다.
      • .big: 22pt, 굵은 폰트 (.bold).
      • .med: 18pt, 반굵은 폰트 (.semibold).
      • .small: 16pt, 기본 굵기 (.regular).

 

5. 필수 생성자

required init?(coder: NSCoder) {
    fatalError("init(coder:) has not been implemented")
}
  • 인터페이스 빌더 사용을 방지합니다. 이 버튼은 코드로만 사용 가능합니다.

 

코드 요약

CustomButton은 버튼의 디자인 및 동작을 단순화하고, 다음과 같은 기능을 제공합니다:

  • 버튼 텍스트와 배경 설정을 간편화.
  • 시스템 스타일과 다크 모드에 적합한 색상 사용.
  • 다양한 폰트 크기 제공.

 

버튼 생성

let loginButton = CustomButton(title: "Login", hasBackground: true, fontSize: .big)
let cancelButton = CustomButton(title: "Cancel", hasBackground: false, fontSize: .small)

버튼 추가 및 레이아웃 설정

view.addSubview(loginButton)
view.addSubview(cancelButton)

loginButton.translatesAutoresizingMaskIntoConstraints = false
NSLayoutConstraint.activate([
    loginButton.centerXAnchor.constraint(equalTo: view.centerXAnchor),
    loginButton.topAnchor.constraint(equalTo: view.topAnchor, constant: 100),
    loginButton.widthAnchor.constraint(equalToConstant: 200),
    loginButton.heightAnchor.constraint(equalToConstant: 50)
])

cancelButton.translatesAutoresizingMaskIntoConstraints = false
NSLayoutConstraint.activate([
    cancelButton.centerXAnchor.constraint(equalTo: view.centerXAnchor),
    cancelButton.topAnchor.constraint(equalTo: loginButton.bottomAnchor, constant: 20),
    cancelButton.widthAnchor.constraint(equalToConstant: 100),
    cancelButton.heightAnchor.constraint(equalToConstant: 40)
])

 

장점

  1. 재사용성:
    • 텍스트, 배경, 폰트 크기를 간단히 설정할 수 있어 여러 화면에서 재사용 가능.
  2. 유지보수성:
    • 버튼 스타일을 통합 관리할 수 있어 유지보수가 용이.
  3. 모던 디자인:
    • 시스템 색상(systemBlue)과 다크 모드 호환으로 최신 UI 트렌드를 따름.

확장 가능성

  • 버튼의 다른 속성(예: 테두리 색상, 텍스트 스타일 등)을 추가하면 다양한 스타일로 확장 가능합니다.

'Project > FirebaseTest' 카테고리의 다른 글

FireBase - 로그인과 로그아웃 처리하는 메서드 정의  (1) 2024.12.03
FireBase - 사용자 등록 기능  (0) 2024.12.03
FireBase - Alert  (0) 2024.12.03
FireBase - UITextView with open WKWebView  (0) 2024.12.03
FireBase - Webkit  (1) 2024.12.03