상세 컨텐츠

본문 제목

[RxSwift] 키보드 높이에 따른 버튼 위치 변경(키보드에 버튼이 가려지는 현상)

iOS 캐기/RxSwift 캐기

by Atlas 2022. 2. 4. 01:31

본문

728x90
반응형

시나리오 : SnapKit과 RxSwift를 사용하여 TextField 클릭 시 키보드 높이에 맞춰 하단 버튼의 위치를 변경해주고 싶음

 

AS-IS 

기존에 구현했던 방법 -> 스토리보드에 화면 구성을 하고 키보드 높이에 따라 버튼의 위치를 변경해줬던 부분 

class ViewController: UIViewController {
    
    @IBOutlet weak var pinNumberTextfield: UITextField!
    @IBOutlet weak var nextBtnBottomConstraint: NSLayoutConstraint!
    
    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view.
        self.navigationItem.title = "created by using storyboard"
    }
    
    @IBAction func nextBtnPressed(_ sender: UIButton) {
        self.pinNumberTextfield.resignFirstResponder()
    }
    
    override func viewWillAppear(_ animated: Bool) {
        super.viewWillAppear(animated)
        self.regiterNotifications()
    }
    override func viewWillDisappear(_ animated: Bool) {
        super.viewWillDisappear(animated)
        self.unRegisterNotification()
    }
    
}

extension ViewController {
    func regiterNotifications(){
        NotificationCenter.default.addObserver(self, selector: #selector(keyboardEvent), name: UIResponder.keyboardWillShowNotification, object: nil)
        NotificationCenter.default.addObserver(self, selector: #selector(keyboardEvent), name: UIResponder.keyboardWillHideNotification, object: nil)
    }
    
    func unRegisterNotification(){
        NotificationCenter.default.removeObserver(self,name:UIResponder.keyboardWillShowNotification, object: nil)
        NotificationCenter.default.removeObserver(self,name:UIResponder.keyboardWillHideNotification, object: nil)
    }
    
    @objc func keyboardEvent(notiInfo: Notification){
        guard let userInfo = notiInfo.userInfo else { return }
        guard let keyboardFrame = (userInfo[UIResponder.keyboardFrameEndUserInfoKey] as? NSValue)?.cgRectValue else { return }
        
        if notiInfo.name == UIResponder.keyboardWillShowNotification {
        	//키보드 높이 + safeArea 하단 영역(X이후 버전대응을 위해서)
            self.nextBtnBottomConstraint.constant = keyboardFrame.height - self.view.safeAreaInsets.bottom
        }else{
            self.nextBtnBottomConstraint.constant = 0
        }
    }
    
    
}

 

To-BE

SnapKit을 통해서 화면구성을 해주고 RxSwift를 이용하여 구현

func keyboardHeight() -> Observable<CGFloat> {
    return Observable
            .from([
                NotificationCenter.default.rx.notification(UIResponder.keyboardWillShowNotification)
                            .map { notification -> CGFloat in
                                (notification.userInfo?[UIResponder.keyboardFrameEndUserInfoKey] as? NSValue)?.cgRectValue.height ?? 0
                            },
                NotificationCenter.default.rx.notification(UIResponder.keyboardWillHideNotification)
                            .map { _ -> CGFloat in
                                0
                            }
            ])
            .merge()
}

//How to use it 
let disposeBag = DisposeBag()
func drawCustomUI(){
...
keyboardHeight()
            .observe(on: MainScheduler.instance)
            .subscribe(onNext: { keyboardHeight in
                let safeAreaBottom = safeArea?.bottom ?? 0
                let height = keyboardHeight > 0.0 ? (keyboardHeight - safeAreaBottom) : safeAreaBottom
                self.updateNextBtnBottom(-height)
                
            })
            .disposed(by: disposeBag)
...
}
            
  func updateNextBtnBottom(_ offset: CGFloat){
        self.nextButton.snp.remakeConstraints {
        	//bottom offset 설정 
            $0.bottom.equalTo(safeAreaLayoutGuide.snp.bottom).offset(offset)
            $0.left.equalTo(0)
            $0.right.equalTo(0)
            $0.height.equalTo(50)
        }
        
    }

 

 

각 각 코드 작성 후 실행 화면 

UIKit + Swift
SnapKit + RxSwift

 

 

마무리 

SnapKit 으로 화면 구성하는 것은 적응하는데 금방 될 거 같음.

RxSwift는 공부를 좀 더 해야겠지만 확실히 코드량이나 가독성 부분에서 좋아 보임. 

 

관련 자료

GitHub:

https://github.com/PotatoArtie/Potato-iOS/tree/master/Labs/KeyboardHeightPotato

 

GitHub - PotatoArtie/Potato-iOS

Contribute to PotatoArtie/Potato-iOS development by creating an account on GitHub.

github.com

 

반응형

댓글 영역