Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

일반회원가입 이메일 입력창 개발 #112

Merged
merged 8 commits into from
Oct 22, 2023
Merged

Conversation

minsangKang
Copy link
Member

개요


변경사항

  • SignupEmailView 구현
  • SignupTextFieldView 커스텀 SwiftUI 구현
  • ScrollViewReader 및 ScrollView를 사용한 TextField 위치로 스크롤 구현
  • 키보드 높이에 따른 content 위치조정 구현
  • mac catalyst 용 하단 버튼추가 구현
  • LoginSignupEnvironment 생성 및 리펙토링
  • SignupEmailView 현지화 반영

키보드에 따른 content 위치조정

목표: 키보드가 표시됨에 따라 입력중인 TextField가 가려지지 않도록 하고자 고민하여 개발

iPhone iPad Mac

목표달성

  • ScrollViewReaderScrollView를 넣고, TextField 마다 id를 부여
  • @FocusState를 통해 입력하고자 하는 TextField를 인지
  • @focusstate의 변화를 .onChange 모디파이어를 통해 인지
  • scrollViewReader의 .scrollTo 모디파이어를 통해 TextField의 상단으로 스크롤되도록 구현
  • 스크롤과 상관없는 Mac의 경우를 분기처리 하기 위하여 #if targetEnvironment(macCatalyst) 구문 추가

에러사항

  • SwiftUI 내에서 표시되는 컨텐츠의 크기를 얻는 수단으로 GeometryReader를 통해 인지
  • 키보드가 표시되면 컨텐츠의 크기가 변화되어 인지, 이러한 현상으로 인해 아이패드의 가로모드지만 아이폰용 UI가 표시되는 문제가 발생
  • 따라서 키보드에 따른 컨텐츠 크기가 변화되지 않도록 .ignoreSafearea(.keyboard) 모디파이어를 적용
  • 하지만 키보드가 표시됨에 따라 스크롤이 되기 위해서는 키보드높이만큼 스크롤뷰의 바닥이 높아져야만 함
  • 따라서 표시되는 키보드의 높이만큼 .padding을 추가하여 문제를 해결함
  • 따라서 아이패드용 UI를 표시하며 키보드가 표시됨에 따른 스크롤이 가능하도록 해결됌
struct SignupEmailView: View {
    @State private var superViewSize: CGSize = .zero
    @ObservedObject private var keyboard = KeyboardResponder()
    
    var body: some View {
        GeometryReader { geometry in
            ZStack {
                ...
                ContentView(superViewSize: $superViewSize)
                    ...
                    .padding(.bottom, keyboard.keyboardHeight)
            }
            .onChange(of: geometry.size, perform: { value in
                self.superViewSize = value
            })
            ...
        }
        ...
        .ignoresSafeArea(.keyboard)
    }
}
struct ContentView: View {
    @EnvironmentObject var environment: LoginSignupEnvironment
    @Binding var superViewSize: CGSize
    @FocusState var focus: SignupTextFieldView.type?
    @State var email: String = ""
    @State var authCode: String = ""
    @State var wrongEmail: Bool?
    @State var wrongAuthCode: Bool?
    
    var body: some View {
        ZStack {
            ScrollViewReader { scrollViewProxy in
                ScrollView {
                    VStack(alignment: .leading, spacing: 0) {
                        ...
                        
                        SignupTextFieldView(type: .email, text: $email, focus: $focus) {
                            emailCheck()
                        }
                        .id(SignupTextFieldView.type.email)
                        ...
                        
                        if wrongEmail == false {
                            ...
                            
                            HStack(alignment: .center, spacing: 16) {
                                SignupTextFieldView(type: .authCode, text: $authCode, focus: $focus) {
                                    authCodeCheck()
                                }
                                .id(SignupTextFieldView.type.authCode)
                                ...
                                
                            }
                            
                            ...
                        }
                    }
                    ...
                    
                    .onChange(of: focus) { newValue in
                        #if targetEnvironment(macCatalyst)
                        #else
                        scrollViewProxy.scrollTo(newValue, anchor: .top)
                        #endif
                    }
                }
                .scrollIndicators(.hidden)
            }
            ...
        }
        .frame(width: abs(self.width), alignment: .leading)
    }
    
    // 화면크기에 따른 width 크기조정
    var width: CGFloat {
        let size = superViewSize
        switch size.deviceDetailType {
        case .iPhoneMini, .iPhonePro, .iPhoneMax:
            return size.minLength - 48
        default:
            return 400
        }
    }
...
}

LoginSignupEnvironment 리펙토링

  • mac catalyst의 경우 NavigationStack 및 environmentObject 관련 이슈가 존재하는 것으로 확인되었다.
  • 따라서 여러 시도를 토대로 environmentObject 전달의 경우 최상단 SwiftUI를 생성시에만 전달하는 식으로 개선
  • 또한 NavigationPath의 경우도 environmentObject 내 함께 지니는 식으로 개선
  • 따라서 자식 뷰에서 navigationPath 및 listener 접근이 필요한 경우 @EnvironmentObject 변수를 통해 접근하는 식으로 개선함.
  • Binding 값이 필요하였기에 @EnvironmentObject 변수를 통해 $environment.navigationPath 식으로 구현함.
import Foundation
import Combine
import SwiftUI

class LoginSignupEnvironment: ObservableObject {
    @Published var dismiss: Bool = false
    @Published var loginSuccess: Bool = false
    @Published var signupSuccess: Bool = false
    @Published var navigationPath = NavigationPath()
}
let hostingVC = UIHostingController(rootView: LoginSelectView().environmentObject(environment))
struct LoginSelectView: View {
    @EnvironmentObject var environment: LoginSignupEnvironment
    @State private var superViewSize: CGSize = .zero
    
    init() {
        //Use this if NavigationBarTitle is with displayMode = .inline
        UINavigationBar.appearance().titleTextAttributes = [.foregroundColor: UIColor.white]
    }
    
    var body: some View {
        NavigationStack(path: $environment.navigationPath) {
        ...
        }
    }
}

Reference

@minsangKang minsangKang added refactor 코드 리펙토링 feature 기능 추가/변경/삭제 ui/ux UI/UX 관련 작업 labels Oct 22, 2023
@minsangKang minsangKang self-assigned this Oct 22, 2023
@minsangKang minsangKang merged commit 914d51a into master Oct 22, 2023
@minsangKang minsangKang deleted the feature/#111 branch October 22, 2023 11:26
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
feature 기능 추가/변경/삭제 refactor 코드 리펙토링 ui/ux UI/UX 관련 작업
Projects
None yet
Development

Successfully merging this pull request may close these issues.

1 participant