프로젝트에서 Side Menu를 구현할 일이 있어 라이브러리를 사용하지 않고 직접 만들어봤습니다.
하단의 코드는 SideMenu가 될 뷰 컨트롤러입니다.
여기에서는 백그라운드와 corner Radius 정도만 설정해줬습니다.
class SideMenuViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
self.view.layer.cornerRadius = 20
self.view.clipsToBounds = true
self.view.backgroundColor = .blue.withAlphaComponent(0.3)
}
}
SideMenu의 상위 뷰(여기서는 ViewController)에서 사용할 SideMenu ViewController와 SideMenu 등장 시 딤 처리할 dimmingView, sideMenu 버튼인 sideMenuButton을 선언해줍니다.
class ViewController: UIViewController {
private var sideMenuViewController = SideMenuViewController()
private var dimmingView: UIView?
private lazy var sideMenuButton = UIImageView().then {
$0.image = UIImage(systemName: "text.justify")
$0.tintColor = .black
let tap = UITapGestureRecognizer(target: self, action: #selector(presentSideMenu))
$0.addGestureRecognizer(tap)
$0.isUserInteractionEnabled = true
}
}
viewDidLoad 에서 UI를 잡아줍니다.
sideMenu가 나타나있을 때, dim 처리 된 배경 클릭 시 sideMenu를 다시 사라지게 하기 위해 handleDimmingViewTap 이라는 제스처를 추가하였습니다.
override func viewDidLoad() {
super.viewDidLoad()
addDimmingView()
}
private func addDimmingView() {
dimmingView = UIView(frame: self.view.bounds)
dimmingView?.backgroundColor = UIColor.black.withAlphaComponent(0.5)
dimmingView?.isHidden = true
view.addSubview(dimmingView!)
let tapGesture = UITapGestureRecognizer(target: self, action: #selector(handleDimmingViewTap))
dimmingView?.addGestureRecognizer(tapGesture)
}
handleDimmingViewTap에서 애니메이션을 통해 side menu를 사라지게 하였습니다.
@objc private func handleDimmingViewTap() {
let sideMenuVC = self.sideMenuViewController
UIView.animate(withDuration: 0.3, animations: {
// 사이드 메뉴를 원래 위치로 되돌림.
sideMenuVC.view.frame = CGRect(x: -self.view.frame.width, y: 0, width: self.view.frame.width, height: self.view.frame.height)
// 어두운 배경 뷰를 숨김.
self.dimmingView?.alpha = 0
}) { (finished) in
// 애니메이션이 완료된 후 사이드 메뉴를 뷰 계층 구조에서 제거.
sideMenuVC.view.removeFromSuperview()
sideMenuVC.removeFromParent()
self.dimmingView?.isHidden = true
}
}
sideMenuButton 클릭 시 동작하는 presentSideMenu 입니다.
높이와 너비를 설정해서 sideMenu의 모양을 커스텀할 수 있습니다.
또한 사이드 메뉴의 크기, yPos, 사이드 메뉴가 나타나기 전 크기와 사이드 메뉴가 화면에 표시될 크기를 조정하시면 다양한 애니메이션을 구현할 수 있습니다.
@objc private func presentSideMenu() {
let sideMenuVC = self.sideMenuViewController
// 사이드 메뉴 뷰 컨트롤러를 자식으로 추가하고 뷰 계층 구조에 추가.
self.addChild(sideMenuVC)
self.view.addSubview(sideMenuVC.view)
// 사이드 메뉴의 너비를 화면 너비의 80%로 설정.
let menuWidth = self.view.frame.width * 0.8
let menuHeight = self.view.frame.height
let yPos = (self.view.frame.height / 2) - (menuHeight / 2) // 중앙에 위치하도록 yPos 계산
// 사이드 메뉴의 시작 위치를 화면 왼쪽 바깥으로 설정.
sideMenuVC.view.frame = CGRect(x: -menuWidth, y: yPos, width: menuWidth, height: menuHeight)
// 어두운 배경 뷰를 보이게 합니다.
self.dimmingView?.isHidden = false
self.dimmingView?.alpha = 0
UIView.animate(withDuration: 0.3, animations: {
// 사이드 메뉴를 화면에 표시.
sideMenuVC.view.frame = CGRect(x: 0, y: yPos, width: menuWidth, height: menuHeight)
// 어두운 배경 뷰의 투명도를 조절.
self.dimmingView?.alpha = 0.5
})
}