[iOS] - 키보드에 동적인 댓글 입력 화면 만들기

sun02·2022년 9월 18일
0

iOS

목록 보기
22/27
post-thumbnail

‼️ 2023.07 추가
여러분분분,, 혹시 최소 타겟이 iOS 15라면 제발 keyboardlayoutGuide 를 사용하십시다 진짜 좋아요

최소 타겟이 15보다 낮으시다면.....화이팅 😅



위와 같이 댓글을 작성할 때 뷰 하단의 댓글 입력 창 (textField)를 가지는 댓글입력View가 키보드 위로 올라오는 화면 구현하기

  • 기존 해결 방안은 view의 bottomAnchor를 키보드 높이 만큼 올려주는 것이었지만, 이 경우 view 위치 조정시 화면상에서의 움직임이 자연스럽지 않다고 판단하였다.

따라서 ScrollView를 조정하여 더 자연스러운 UI를 제공하려고 한다.

1. ScrollView 구현하기

- UIScrollView

  • 스크롤 뷰를 추가한 후 leading, trailing, top, bottom을 safeArea에 딱맞게 적용해준다

- UIStackView

  • ScrollView안에 StackView를 추가
  • StackView의 width를 scrollView의 width와 동일하게 설정
    • 세로 스크롤을 구현하기 위함. 가로 스크롤이 되어야하는 경우에는 Height를 동일하게 설정
  • StackView의 leading, trailing, top, bottom은 scrollview의 Content Layout Guide와 같게 설정
    • Content Layout Guide : ScrollView 안에 들어가는 content들의 레이아웃으로, 컨텐츠에 따라 늘어나는 스크롤 뷰 내의 영역을 말한다.

💡 ScrollView 내부를 StackView로 구성한 이유?
: ScrollView 내부를 UIView로 구성하게 되면, 해당 UIView의 높이가 고정되지 않는 경우 스크롤이 되지 않는 이슈가 발생하기에 stackView를 사용하여 높이 고정 이슈 해결할 수 있다.

2. Keyboard 활성화 여부에 따라 ScrollView 조절하기

keyboard가 활성화되었을 때 scrollView를 위로 올리고, 비활성화되었을 때 scrollView를 아래로 내려야한다.

그러나 그 시점을 계산할 수 없기 때문에 이를 알려주는 observer가 필요한데

💡 UIKit은 UIResponder.keyboardWillShowNotification, UIResponder.keyboardWillHideNotification 를 내장하고 있다

따라서 NotificationCenter에 위 observer들을 추가해주기만 하면 된다

- addkeyBoardObeserver

func addKeyboardObserver() {
        NotificationCenter.default.addObserver(self,
                                               selector: #selector(keyboardWillShow(_:)),
                                               name: UIResponder.keyboardWillShowNotification,
                                               object: nil)
        
        NotificationCenter.default.addObserver(self,
                                               selector: #selector(keyboardWillHide(_:)),
                                               name: UIResponder.keyboardWillHideNotification,
                                               object: nil)
    }
  • 첫 번째 observer는 keyboard가 나타나려할 때 keyboardWillShow(_:) 함수를 호출한다
  • 두 번째 observer는 keyboard가 사라지려할 때 keyboardWillHide(_:) 함수를 호출한다.

따라서 이제 각 함수에 Keyboard의 높이만큼 ScrollView의 높이를 올리거나, 내리를 코드를 작성하면 된다

- KeyboardWillShow(_:)

 @objc private func keyboardWillShow(_ notification: Notification) {
        guard let userInfo = notification.userInfo as NSDictionary?,
              let keyboardFrame = (userInfo[UIResponder.keyboardFrameEndUserInfoKey] as? NSValue)?.cgRectValue else {
                  return
              }
        /// 키보드의 높이
        let keyboardHeight = keyboardFrame.size.height
        /// 댓글 입력(textField)를 포함하고 있는 View
        let commentViewHeight = 61.0
        
        commentViewBottomConstraint.constant = keyboardHeight - self.view.safeAreaInsets.bottom
        scrollView.contentOffset.y = keyboardHeight + commentViewHeight
        
        UIView.animate(withDuration: 0.3,
                       animations: { self.view.layoutIfNeeded()},
                       completion: nil)
    }
  • commentViewBottomConstraint: 댓글입력 View의 bottom layout constraint
    • 일반적으로 view의 bottom에 붙어 있지만 키보드가 활성화되면 키보드 위로 올라가야한다.
    • 따라서, keyboardHeight에서 safeAreaInset.bottom을 제외한 값을 bottom constant로 넣어준다.
  • scrollView.contentOffset.y: 스크롤뷰가 위로 스크롤된 정도
    • 키보드가 활성화될 때 scrollView가 키보드의 높이 + 댓글 입력 뷰 만큼 위로 스크롤되어야한다.
    • 따라서 contentOffset.y를 키보드의 높이 + 댓글 입력 뷰로 설정한다.

- keyboardWillHide(_:)

 @objc private func keyboardWillHide(_ notification: NSNotification) {
        scrollView.contentOffset.y = .zero
        scrollView.scrollIndicatorInsets = self.scrollView.contentInset
        commentViewBottomConstraint.constant = .zero
        
        UIView.animate(withDuration: 0.3,
                       animations: { self.view.layoutIfNeeded()},
                       completion: nil)
    }

키보드가 비활성화 되는 경우 댓글 입력 창과 scrollView 둘 다 view의 bottom으로 내려와야한다. 따라서 .zero 값을 넣어주면 된다

  • scrollView의 contentOffset이 조절될 때 scrollViewIndicator가 즉시 그에 맞게 조절되지 않기 때문에 위와 같이 설정해주어야한다.

- removeKeyBoardObserver

 func removeKeyBoardObserver() {
        NotificationCenter.default.removeObserver(UIResponder.keyboardWillShowNotification)
        NotificationCenter.default.removeObserver(UIResponder.keyboardWillHideNotification)
    }

마지막으로, 이 viewController를 벗어나면 이 observer들은 더이상 필요가 없기 때문에 viewWillDisappear에서 이 removeKeyBoardObserver()를 호출하여 observer를 제거한다.

0개의 댓글