본문 바로가기
Project/FirebaseTest

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

by 밤새는 탐험가89 2024. 12. 2.
728x90
SMALL

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

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

 

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

 

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

 

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 트렌드를 따름.

확장 가능성

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

'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