본문 바로가기

iOS

[ iOS / Swift ] 온보딩(Onboarding) 화면 만들기 - (1) UIPageControl, UIPageViewController

 

 

UIPageViewController, UIPageControl을 이용해서 위의 화면과 같은 온보딩 화면을 만들려고 한다.

이 온보딩 화면은 3가지 방법으로 페이지 이동이 가능하다.

- 스와이프를 이용한 페이지 이동 

- 페이지 컨트롤 이용한 페이지 이동

- 다음 버튼을 이용한 페이지 이동

 

 

1. 온보딩 화면을 만들 뷰컨트롤러에 Container View를 추가하고 컨테이너뷰를 추가하면서 생긴 뷰 컨트롤러를 삭제해 준다.

 

컨테이너뷰를 추가하면 왼쪽 사진처럼 컨테이너뷰에 연결된 뷰컨트롤러 하나가 같이 생성된다. 같이 생성된 뷰 컨트롤러를 삭제해 주면 된다. 삭제하고 나면 오른쪽 사진처럼 컨테이너뷰만 남게 된다.

 

2. UIPageViewController를 추가해 준 후 control을 눌러서 컨테이너뷰에서 페이지 뷰컨트롤러로 연결시켜 준 후 Embed를 선택해 준다.

 

 

3. UIPageControl을 원하는 위치에 추가해 준다.

뷰컨트롤러에 아웃렛도 설정해 준다.

4. 온보딩 화면에 들어갈 페이지들의 뷰 컨트롤러들을 추가해 준다.

 

페이지 뷰 컨트롤러에서 스토리보드아이디를 사용해야 하기 때문에 각 뷰컨트롤러에 스토리보드아이디를 설정해 준다.

 

 

 

5. 그럼 이제 페이지 뷰 컨트롤러 설정부터 해주겠다.

우선 온보드페이지뷰컨트롤러 파일을 생성하여 스토리보드의 온보드페이지 뷰컨트롤러와 연결해 준다.

 

 

 

6. 페이지뷰컨트롤러에 온보딩 뷰컨트롤러 리스트를 생성해 준다.

UIStoryBoardsms 온보딩 화면이 있는 스토리보드의 이름을 넣어서 가져올 수 있도록 한다.

 

withIdentifi는 위에서 설정해 준 각 화면의 스토리보드아이디를 넣어준다.

 

setViewControllers를 통해 리스트의 맨 처음 뷰컨트롤러를 보여주도록 설정해 준다.

 

import UIKit

class OnboardPageViewController: UIPageViewController {
    
    var contentPageViewControllerList = [UIViewController]()

    override func viewDidLoad() {
        super.viewDidLoad()

        let storyBoard = UIStoryboard(name: "Main", bundle: nil)
        
        contentPageViewControllerList = [
            storyBoard.instantiateViewController(withIdentifier: "OneOnboard"),
            storyBoard.instantiateViewController(withIdentifier: "TwoOnboard"),
            storyBoard.instantiateViewController(withIdentifier: "ThreeOnboard"),
            storyBoard.instantiateViewController(withIdentifier: "FourOnboard"),
            storyBoard.instantiateViewController(withIdentifier: "FiveOnboard")
        ]
        
        setViewControllers([contentPageViewControllerList[0]], direction: .forward, animated: false, completion: nil)
    }
    

}

 

 

 

7. 이제 페이지 뷰 컨트롤러의 datasource와 delegate를 설정해 준다.

  • 7-1 데이터소스 설정

viewControllerBefore

- 이전 화면으로 스와이프 하면 이전 화면으로 어떤 뷰를 보여줄지 결정해 주는 데이터소스

 

viewControllerAfter

- 다음화면으로 스와이프하면 다음화면으로 어떤 뷰를 보여줄지 결정해주는 데이터 소스 

 

extension OnboardPageViewController: UIPageViewControllerDataSource {
    
    func pageViewController(_ pageViewController: UIPageViewController, viewControllerBefore viewController: UIViewController) -> UIViewController? {
        let currentIndex = contentPageViewControllerList.firstIndex(of: viewController)!
        if currentIndex == 0 {
            return nil
        } else {
            return contentPageViewControllerList[currentIndex - 1]
        }
    }
    
    func pageViewController(_ pageViewController: UIPageViewController, viewControllerAfter viewController: UIViewController) -> UIViewController? {
        let currentIndex = contentPageViewControllerList.firstIndex(of: viewController)!
        if currentIndex == contentPageViewControllerList.count - 1 {
            return nil
        } else {
            return contentPageViewControllerList[currentIndex + 1]
        }
    }
    
}

 

  • 7-2 델리게이트 설정

didFinishAnimating 페이지 이동 움직임이 끝났을 때 실행해 줄 것을 설정해 주는 것이다.

 

여기서는 페이지 이동이 끝났을 때 페이지 컨트롤도 이동된 위치의 인덱스를 표현해 주도록 설정해 준다.

뒤에서 다시 걸정 해주겠다.

 

extension TutorialPageViewController: UIPageViewControllerDelegate {
    func pageViewController(_ pageViewController: UIPageViewController, didFinishAnimating finished: Bool, previousViewControllers: [UIViewController], transitionCompleted completed: Bool) {
        
    }
    
}

 

 

  • 7-3 goToPage 함수 추가

데이터소스 델리게이트 외에도 

우리는 페이지컨트롤을 이용해서도 페이지 이동이 가능해야 하기 때문에

페이지 컨트롤이 있는 뷰컨트롤러에서도 페이지뷰컨트롤러의 페이지를 이동시킬 수 있도록 goToPage라는 함수 하나를 추가해 준다.

import UIKit

class OnboardPageViewController: UIPageViewController {
    
    var contentPageViewControllerList = [UIViewController]()

    override func viewDidLoad() {
        super.viewDidLoad()

        let storyBoard = UIStoryboard(name: "Main", bundle: nil)
        
        contentPageViewControllerList = [
            storyBoard.instantiateViewController(withIdentifier: "OneOnboard"),
            storyBoard.instantiateViewController(withIdentifier: "TwoOnboard"),
            storyBoard.instantiateViewController(withIdentifier: "ThreeOnboard"),
            storyBoard.instantiateViewController(withIdentifier: "FourOnboard"),
            storyBoard.instantiateViewController(withIdentifier: "FiveOnboard")
        ]
        
        setViewControllers([contentPageViewControllerList[0]], direction: .forward, animated: false, completion: nil)
    }
    
    func goToPage(index: Int) {
        let currentViewController = viewControllers!.first!
        let currentViewControllerIndex = contentPageViewControllerList.firstIndex(of: currentViewController)!
        
        let direction: NavigationDirection = index > currentViewControllerIndex ? .forward : .reverse
        setViewControllers([contentPageViewControllerList[index]], direction: direction, animated: false, completion: nil)
    }
    

}

 

다음에 이어서!