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)
}
}
}