관리 메뉴

김종권의 iOS 앱 개발 알아가기

[iOS - swift] TextField를 클릭시 버튼 올라오게 하기 (RxKeyboard, layoutSubviews) 본문

iOS 응용 (swift)

[iOS - swift] TextField를 클릭시 버튼 올라오게 하기 (RxKeyboard, layoutSubviews)

jake-kim 2020. 8. 17. 14:55

main run loop


Main Run Loop : 사용자의 이벤트를 받아들이거나, response 하는 때

Update Cycle: Main Run Loop에서 response를 리턴한 경우 진입 (이 때 레이아웃을 재배치하거나 view를 그림)

* iOS앱은 60fps이므로 update cycle의 주기도 1/60초 -> 뷰를 갱신하고 싶어도 이 갱신 주기를 기다려야함

layoutSubviews()


이 메소드는 위에서 레이아웃을 재배치할 때 사용되는 UIView의 메소드 (expensive하기 때문에 다른 메소드를 통해 간접적으로 호출)

1) setNeedsUpdate() : 다음 update cycle에 레이아웃을 갱신

2) layoutIfNeeded(): 즉시 레이아웃을 갱신하라

텍스트필드 클릭시 키보드와 함께 버튼이 올라오게 하려면 layoutIfNeeded()를 사용

텍스트필드 레이아웃 배치


오른쪽에 짤리는 것을 방지하여 <=로 할당
확인 버튼이 올라오게 만들 것

확인 버튼의 bottom constraint를 IBOutlet으로 바꾼 후,

height를 keyboard가 올라온 높이만큼 지정해주면 완성

// BaseViewController.swift

    func raiseKeyboardWithButton(keyboardChangedHeight: CGFloat, constraintBetweenBtnAndKeyboard: NSLayoutConstraint) {
        DispatchQueue.main.async {
            UIView.animate(withDuration: 0.23, animations: {
                var safeAreaBottomLength = self.view.safeAreaInsets.bottom

                if keyboardChangedHeight == 0 { // 버튼이 가라앉는 버그 대응
                    safeAreaBottomLength = 0
                }

                constraintBetweenBtnAndKeyboard.constant = keyboardChangedHeight - safeAreaBottomLength + Constants.ComponentStyle.intervalSizeBetweenButtonAndKeyboard
                self.view.layoutIfNeeded()
            })
        }
    }
import UIKit
import RxSwift
import RxCocoa
import RxKeyboard

class ViewController: BaseViewController {

    @IBOutlet weak var btnBottomConstraint: NSLayoutConstraint!
    @IBOutlet weak var tf: UITextField!

    let disposeBag = DisposeBag()

    override func viewDidLoad() {
        super.viewDidLoad()

        setUpOutputBinding()
    }

    override func viewDidAppear(_ animated: Bool) {
        tf.becomeFirstResponder()
    }
    
    func setUpOutputBinding() {
        RxKeyboard.instance.visibleHeight
            .drive(rx.keyboardHeightChanged)
        .disposed(by: disposeBag)
    }

}

extension Reactive where Base: LoginVC {
    var keyboardHeightChanged: Binder<CGFloat> {
        return Binder(base) { vc, height in
            vc.raiseKeyboardWithButton(keyboardChangedHeight: height, constraintBetweenBtnAndKeyboard: vc.btnVerifyBottomConstraint)
        }
    }
}

 

Comments