Swift를 활용한 Bottom Sheet 애니메이션 효과 추가하기

작성일 :

Swift를 활용한 Bottom Sheet 애니메이션 효과 추가하기

iOS 애플리케이션에서 자주 보게 되는 UI 요소 중 하나는 Bottom Sheet입니다. 이는 화면 하단에서 슬라이드하여 올라오는 형태로 다양한 인터랙션을 제공합니다. 이번 글에서는 Swift를 활용하여 Bottom Sheet를 구현하고, 원하는 대로 애니메이션 효과를 추가하는 방법을 자세히 설명하겠습니다.

Bottom Sheet의 기본 개요

Bottom Sheet는 화면의 하단에서 슬라이드하여 올라오고, 사용자 동작에 따라 닫히거나 열릴 수 있습니다. 주로 UIViewControllerUIView를 사용하여 구성되오며, Auto Layout과 애니메이션을 활용해 사용자에게 매끄러운 경험을 제공합니다.

필요한 요소들

  1. UIViewController - Bottom Sheet를 표시할 뷰 컨트롤러
  2. UIView - Bottom Sheet에 포함될 뷰
  3. Auto Layout Constraints - Bottom Sheet의 위치와 크기를 제어
  4. UIGestureRecognizer - 드래그 및 터치 동작을 감지
  5. UIViewPropertyAnimator - 애니메이션 적용

구현 단계

1. 프로젝트 설정

Swift로 Bottom Sheet를 구현하기 위해 새로운 Xcode 프로젝트를 생성합니다. Single View App을 선택하고, 프로젝트 이름을 지정합니다. 이후 뷰 컨트롤러에서 작업을 진행합니다.

swift
import UIKit

class ViewController: UIViewController {
    var bottomSheetView: UIView!
    var bottomSheetHeight: CGFloat = 300
    var bottomSheetTopConstraint: NSLayoutConstraint!

    override func viewDidLoad() {
        super.viewDidLoad()
        setupBottomSheet()
    }

    func setupBottomSheet() {
        bottomSheetView = UIView()
        bottomSheetView.backgroundColor = .white
        bottomSheetView.layer.cornerRadius = 16
        bottomSheetView.translatesAutoresizingMaskIntoConstraints = false
        view.addSubview(bottomSheetView)

        NSLayoutConstraint.activate([
            bottomSheetView.leadingAnchor.constraint(equalTo: view.leadingAnchor),
            bottomSheetView.trailingAnchor.constraint(equalTo: view.trailingAnchor),
            bottomSheetView.heightAnchor.constraint(equalToConstant: bottomSheetHeight),
        ])
        bottomSheetTopConstraint = bottomSheetView.topAnchor.constraint(equalTo: view.bottomAnchor)
        bottomSheetTopConstraint.isActive = true
    }
}

2. 애니메이션 적용

이번에는 Bottom Sheet를 화면 상단으로 슬라이드할 수 있도록 애니메이션을 추가합니다. 이를 위해 UIViewPropertyAnimator를 사용하여 애니메이션을 추가합니다.

swift
class ViewController: UIViewController {
    var bottomSheetView: UIView!
    var bottomSheetHeight: CGFloat = 300
    var bottomSheetTopConstraint: NSLayoutConstraint!

    override func viewDidLoad() {
        super.viewDidLoad()
        setupBottomSheet()
        setupGesture() // 제스처 설정 함수 추가
    }

    func setupBottomSheet() {
        bottomSheetView = UIView()
        bottomSheetView.backgroundColor = .white
        bottomSheetView.layer.cornerRadius = 16
        bottomSheetView.translatesAutoresizingMaskIntoConstraints = false
        view.addSubview(bottomSheetView)

        NSLayoutConstraint.activate([
            bottomSheetView.leadingAnchor.constraint(equalTo: view.leadingAnchor),
            bottomSheetView.trailingAnchor.constraint(equalTo: view.trailingAnchor),
            bottomSheetView.heightAnchor.constraint(equalToConstant: bottomSheetHeight),
        ])
        bottomSheetTopConstraint = bottomSheetView.topAnchor.constraint(equalTo: view.bottomAnchor)
        bottomSheetTopConstraint.isActive = true
    }

    func setupGesture() {
        let panGesture = UIPanGestureRecognizer(target: self, action: #selector(handlePanGesture(_:)))
        bottomSheetView.addGestureRecognizer(panGesture)
    }

    @objc func handlePanGesture(_ recognizer: UIPanGestureRecognizer) {
        let translation = recognizer.translation(in: view)
        if recognizer.state == .changed {
            bottomSheetTopConstraint.constant = -translation.y
        } else if recognizer.state == .ended {
            if translation.y < bottomSheetHeight / 2 {
                animateBottomSheet(to: 0)
            } else {
                animateBottomSheet(to: bottomSheetHeight)
            }
        }
    }

    func animateBottomSheet(to constant: CGFloat) {
        UIViewPropertyAnimator(duration: 0.3, dampingRatio: 1.0) {
            self.bottomSheetTopConstraint.constant = constant
            self.view.layoutIfNeeded()
        }.startAnimation()
    }
}

이 코드는 사용자가 Bottom Sheet를 드래그할 때 위치를 변경하고, 드래그가 끝나면 애니메이션을 통해 최종 위치로 이동합니다.

3. 고급 애니메이션 효과 추가

이번에는 더욱 매끄러운 경험을 위해 추가적인 애니메이션 효과를 적용합니다. 예를 들어, Bottom Sheet가 열리면서 배경 뷰의 알파 값을 조절하여 어두운 배경을 만들 수 있습니다.

swift
class ViewController: UIViewController {
    var bottomSheetView: UIView!
    var bottomSheetHeight: CGFloat = 300
    var bottomSheetTopConstraint: NSLayoutConstraint!
    var dimmingView: UIView!

    override func viewDidLoad() {
        super.viewDidLoad()
        setupDimmingView()
        setupBottomSheet()
        setupGesture()
    }

    func setupDimmingView() {
        dimmingView = UIView()
        dimmingView.backgroundColor = UIColor.black.withAlphaComponent(0.5)
        dimmingView.alpha = 0
        dimmingView.translatesAutoresizingMaskIntoConstraints = false
        view.addSubview(dimmingView)

        NSLayoutConstraint.activate([
            dimmingView.leadingAnchor.constraint(equalTo: view.leadingAnchor),
            dimmingView.trailingAnchor.constraint(equalTo: view.trailingAnchor),
            dimmingView.topAnchor.constraint(equalTo: view.topAnchor),
            dimmingView.bottomAnchor.constraint(equalTo: view.bottomAnchor),
        ])
    }

    @objc func handlePanGesture(_ recognizer: UIPanGestureRecognizer) {
        let translation = recognizer.translation(in: view)
        if recognizer.state == .changed {
            bottomSheetTopConstraint.constant = -translation.y
            dimmingView.alpha = min(1, max(0, (-translation.y / bottomSheetHeight)))
        } else if recognizer.state == .ended {
            if translation.y < bottomSheetHeight / 2 {
                animateBottomSheet(to: 0)
            } else {
                animateBottomSheet(to: bottomSheetHeight)
            }
        }
    }

    func animateBottomSheet(to constant: CGFloat) {
        UIViewPropertyAnimator(duration: 0.3, dampingRatio: 1.0) {
            self.bottomSheetTopConstraint.constant = constant
            self.dimmingView.alpha = (constant == 0) ? 1 : 0
            self.view.layoutIfNeeded()
        }.startAnimation()
    }
}

이 코드는 Bottom Sheet가 열리고 닫히는 동안 배경 뷰의 알파 값을 조절하여 어두운 배경을 생성합니다. 이를 통해 Bottom Sheet를 열 때 더 나은 사용자 경험을 제공할 수 있습니다.

결론

Swift를 활용하여 iOS 애플리케이션에 Bottom Sheet를 구현하고 애니메이션 효과를 추가하는 방법에 대해 알아보았습니다. UIKit과 Swift의 애니메이션 API를 잘 활용하면, 사용자에게 매끄럽고 직관적인 인터페이스를 제공할 수 있습니다. 이 글을 통해 여러분의 프로젝트에 더욱 다채롭고 매력적인 UI를 구축하는데 도움이 되었기를 바랍니다.