본문 바로가기

iOS/니카내카

[니카내카] Bottom Sheet Using UISheetPresentationController

728x90

니카내카 앱 화면 중 메인에서 정보를 불러 온 다음 지도의 핀을 누르면 아래에서 화면이 있다.

핀에 해당하는 쏘카/그린카의 예약 현황 정보를 간단하게 바텀 시트로 제공하는 화면이었고 그림으로는 아래와 같다.

 

이 화면을 구현할 방법을 고민했었는데 .. 크게 세가지 정도로 리스트 업 할 수 있었다.

  1. ViewController + View 로 구현
  2. PanModal 라이브러리 사용
  3. UISheetPresentationController 사용

... 이 중에서 무엇을 사용해서 구현을 할까 고민을 하다가 .. !! 첫번째 방법과 두번째 방법은 이전에 해보았기에 세번째 방법을 사용해보기로 했다.

 

UISheetPresentationController가 무엇인가?!

그동안 우리가 많이 사용했던 모달 방식에서 화면 전환을 할 때 아래와 같이 작성한 적이 많다.

// 1.
let modalViewController = ModalViewController()
self.present(modalViewController, animated: true)

// 2. 
let modalViewController = ModalViewController()
modalViewController.modalPresentationStyle = .fullScreen
self.present(modalViewController, animated: true)

기본적으로 첫번째 방식으로 화면이 전환되지만, 

어떤 모달 스타일로 뷰를 띄울 것인지를 두번째 방법처럼  설정할 수 있다.

 

위와 같이 fullScreen으로 설정을 하면 부모 뷰의 전체 뷰를 덮는 방식으로 모달이 나타난다. 

 

별도의 값을 설정하지 않으면 적용되는 modalPresentationStyle의 기본 값은 automatic이다. 

automatic이 적용된 대부분의 View Controller는 pageSheet 스타일로 설정된다. 

 

여기까지가 우리가 자주 사용하고 잘 알고 있는 modalPresentationStyle이다.

 

만약 여기서 해당 값을 pageSheet 또는 formSheet로 설정하면 어떻게 될까?

➡️ 단어를 통해서 알 수 있는 것처럼 sheet 형식으로 보이게 된다.

➡️ 그리고 해당 View Controller의 var sheetPresentationController: UISheetPresentationController 프로퍼티에 값이 담기게 된다. (위의 코드처럼 모달 스타일을 fullScreen 등으로 설정을 하게 되면 이 값은 nil이 된다.)

 

 

그래서 !! UISheetPresentationController가 무엇을 하는 친구냐 !?

바로 sheet의 모양과 동작을 관리하는 presentation controller이다. (UIPresentationController를 상속받고 있다.)

 

그래서 만약 ViewController에서 아래와 같이 sheetPresentationController에 접근해서 UISheetPresentationController의 프로퍼티 세팅을 통해 동작과 모양을 설정할 수 있다.

 

private func configureSheet() {
    isModalInPresentation = false
    
    if let sheet = sheetPresentationController {
        sheet.detents = [.medium(), .large()]
        sheet.selectedDetentIdentifier = .medium
        sheet.largestUndimmedDetentIdentifier = .none
        sheet.prefersScrollingExpandsWhenScrolledToEdge = false
        sheet.prefersGrabberVisible = true
        sheet.preferredCornerRadius = 20
    }
}

 

각 코드가 어떤 것을 설정하는지 알아보자면,

 

isModalInPresentation = false

밑으로 내렸을 때 dismiss를 할 수 있도록 허용하는지/허용하지 않는지 설정

true로 설정하면 내려가지 않고 false로 설정하면 내려간다.

 

sheet.detents = [.medium(), .large()]

드래그를 멈추면 그 위치에서 멈추는 지점을 설정

기본 값은 large()이다.

 

sheet.selectedDetentIdentifier = .medium

초기화 드래그 위치 설정

 

sheet.largestUndimmedDetentIdentifier = .none

sheet 아래에 위치하는 ViewController를 흐려지지 않게 하는 경계값으로

만약 .medium으로 설정한다면 그 이상일 때, 즉 large일 때 흐려지도록 설정된다.

 

sheet.prefersScrollingExpandsWhenScrolledToEdge = false

sheet로 presentehls  ViewController 내부를 scroll 하면 sheet가 움직이지 않고 내부 컨텐츠가 스크롤 되도록 설정 

 

sheet.prefersGrabberVisible = true

grabber 바가 보이도록 설정 

 

sheet.preferredCornerRadius = 20

곡률값 설정 

 


이렇게 원하는 속성을 설정해서 화면을 만들어주면 위의 UI와 같은 화면이 구현된다 !!