[swift] 좀 더 자연스럽게 키보드에 반응해서 화면올리기


1️⃣ 목표

  • 오른쪽과 같은 반응형 키보드 만들었습니다.
  • 하지만 만드는 방법은 구글 유튜브등 자료가 많이 있기 때문에 생략하겠습니다.(본인은 정대리youtube - API 프로젝트영상을 참고)
  • 이번 포스터에서는 만드는 과정에서 생긴 문제점에 대해 정리할 예정입니다
  • finished version
    • 이렇게 키보드에 반응하여 입력창확인버튼을 보이게 하는 것은 Apple-human-interface-guidelines에도 나와 있듯이 애플공식사이트에서도 권장하고 있습니다.

    2️⃣ 문제발생

    (1) 문제점

    • 기존에는 다음과 같이 버튼의 frame.origin.y값만큼 뷰 전체의 Y좌표를 조절하는 식으로 구현했습니다.
    if let keyboardSize = (notification.userInfo?[UIResponder.keyboardFrameEndUserInfoKey] as? NSValue)?.cgRectValue {
        let distance = keyboardSize.height - (UIScreen.main.bounds.height - confirmBtn.frame.origin.y - confirmBtn.frame.height)
    
        if (self.view.frame.origin.y + distance > 0) {
            self.view.frame.origin.y -= distance
        }
    }
    
  • 하지만 생각했던 것 처럼 화면이 올라가지 않았습니다.
  • 추가적으로 화면 전체가 통째로 올라가다 보니 관련없는부분의 UI도 신경써야되는 불편함이 있었습니다. (오른쪽 이미지에서 "메인 뷰"부분)
  • frame problem
  • 추가로 화면 전체의 뷰를 이동시키면 키보드를 닫을 때 검은부분이 보이는데 이것도 부자연스럽게 보입니다. (오른쪽 짤의 키보드가 사라지는 부분을 봐보자)
  • temp responsive keyboard

    (2) 원인

  • 생각했던 것 만큼 화면이 올라가지 않았던 것은 frame에 대한 개념을 잘못 알고 있었던 것이 원인이 였습니다.
  • frame은 상위뷰를 기준으로 잡히게 되는데 제대로된 거리를 구하기 위해서는 상위뷰의 frame좌표를 모두 고려해서 계산해야 합니다.
  • frame과 bounds에 대한 개념은 https://zeddios.tistory.com/203를 참고하면 될 것 같습니다.
  • reason

    3️⃣ 해결방법

    • 해결해야할 문제는 다음과 같습니다.
      1. 정확한 좌표로 버튼이 제대로 보이게 만들기
      2. 관련없는 부분의 UI를 고려하지않고 독립적으로 동작하도록하기
      3. 키보드가 사라질때 검은부분이 보이지 않게 하기
  • 위의 세가지 문제점한가지 방법으로 모두 해결가능합니다.
  • 입력에 관련된 부분만 임시 뷰로 감싸는 것 입니다.
  • 전체 화면의 좌표를 조절하는 것 대신에 임시 뷰의 좌표를 대신 조정하는 것 입니다.
  • solution
    • 이렇게 임시 뷰를 만들어 스텍으로 감싸게 되면다음과 같은 장점이 있습니다.
      1. 좀 더 가시적으로 좌표를 구할 수 있다.
      2. 임시 뷰안에서 마음껏 수정해도 좌표에 영향을 주지 않고, 관련없는 부분의 UI를 신경쓸 필요없다.(유연성)
      3. 키보드가 사라질때 검은부분이 보이지 않는다. (자연스러운 UI)
    • 또한 다음과 같이 스크롤 뷰에서도 임시 뷰로 감싸는 것이 UI적으로 깔끔합니다.

    < 스택 사용 X >

    bad_example_in_scrollView

    < 스택 사용 O >

    good_example_in_scrollView
    • 다음은 스크롤뷰에서 사용시 키보드반응 좌표식 입니다.
    if let keyboardSize = (notification.userInfo?[UIResponder.keyboardFrameEndUserInfoKey] as? NSValue)?.cgRectValue {
        let distance = keyboardSize.height
            - (UIScreen.main.bounds.height - self.myView.frame.origin.y
                - self.myView.frame.height - self.myScrollView.frame.origin.y
                + self.myScrollView.contentOffset.y)
        self.myView.frame.origin.y -= distance
    }
    




    © 2021.02. by kirim

    Powered by kkrim