Я создал пример проекта для этого вопроса. Вы можете увидеть результат на изображении выше. По сути, я создал класс-оболочку для боковой панели, а затем использовал его всякий раз, когда захочу:)
Боковая панель
import UIKit
protocol SidebarDelegate {
func sidbarDidOpen()
func sidebarDidClose(with item: Int?)
}
class SidebarLauncher: NSObject{
var view: UIView?
var delegate: SidebarDelegate?
var vc: NavigationViewController?
init(delegate: SidebarDelegate) {
super.init()
self.delegate = delegate
}
func show(){
let bounds = UIScreen.main.bounds
let v = UIView(frame: CGRect(x: -bounds.width, y: 0, width: bounds.width, height: bounds.height))
v.backgroundColor = .clear
let vc = UIStoryboard.init(name: "Main", bundle: nil).instantiateViewController(withIdentifier: "NavigationController") as! NavigationViewController
v.addSubview(vc.view)
vc.view.translatesAutoresizingMaskIntoConstraints = false
NSLayoutConstraint.activate([
vc.view.topAnchor.constraint(equalTo: v.topAnchor),
vc.view.leadingAnchor.constraint(equalTo: v.leadingAnchor),
vc.view.bottomAnchor.constraint(equalTo: v.bottomAnchor),
vc.view.trailingAnchor.constraint(equalTo: v.trailingAnchor, constant: -60)
])
vc.delegate = self
v.isUserInteractionEnabled = true
v.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(handleTapGesture(_:))))
self.view = v
self.vc = vc
UIApplication.shared.keyWindow?.addSubview(v)
UIView.animate(withDuration: 0.5, delay: 0, usingSpringWithDamping: 1, initialSpringVelocity: 1, options: [.curveEaseOut], animations: {
self.view?.frame = CGRect(x: 0, y: 0, width: self.view!.frame.width, height: self.view!.frame.height)
self.view?.backgroundColor = UIColor.black.withAlphaComponent(0.5)
}, completion: {completed in
self.delegate?.sidbarDidOpen()
})
}
@objc func handleTapGesture(_ sender: UITapGestureRecognizer){
closeSidebar(option: nil)
}
func closeSidebar(option: Int?){
UIView.animate(withDuration: 0.5, delay: 0, usingSpringWithDamping: 1, initialSpringVelocity: 1, options: [.curveEaseOut], animations: {
if let view = self.view{
view.frame = CGRect(x: -view.frame.width, y: 0, width: view.frame.width, height: view.frame.height)
self.view?.backgroundColor = .clear
}
}, completion: {completed in
self.view?.removeFromSuperview()
self.view = nil
self.vc = nil
self.delegate?.sidebarDidClose(with: option)
})
}
}
extension SidebarLauncher: NavigationDelegate{
func navigation(didSelect: Int?) {
closeSidebar(option: didSelect)
}
}
NavigationController
import UIKit
protocol NavigationDelegate{
func navigation(didSelect: Int?)
}
class NavigationViewController: UIViewController{
@IBOutlet weak var buttonLaunchVC: UIButton!
@IBOutlet weak var buttonSecondViewController: UIButton!
@IBOutlet weak var buttonThirdViewController: UIButton!
var delegate: NavigationDelegate?
override func viewDidLoad() {
super.viewDidLoad()
[buttonLaunchVC,buttonSecondViewController,buttonThirdViewController].forEach({
$0?.addTarget(self, action: #selector(didSelect(_:)), for: .touchUpInside)
})
}
@objc func didSelect(_ sender: UIButton){
switch sender {
case buttonLaunchVC:
delegate?.navigation(didSelect: 0)
case buttonSecondViewController:
delegate?.navigation(didSelect: 1)
case buttonThirdViewController:
delegate?.navigation(didSelect: 2)
default:
break
}
}
@IBAction func CloseMenu(_ sender: Any) {
delegate?.navigation(didSelect: nil)
}
}
ViewController
class ViewController: UIViewController {
@IBAction func OpenMenu(_ sender: Any) {
SidebarLauncher(delegate: self ).show()
}
}
extension ViewController: SidebarDelegate{
func sidbarDidOpen() {
print("Sidebar opened")
}
func sidebarDidClose(with item: Int?) {
guard let item = item else {return}
print("Did select \(item)")
switch item {
case 0:
break
case 1:
let v = UIStoryboard.main.SecondVC()
present(v!, animated: true)
case 2:
let v = UIStoryboard.main.ThirdVC()
present(v!, animated: true)
default:
break
}
}
Основная область интересов SidebarLauncher класс
что он делает: когда вы вызываете метод show () . он создает UIView, затем добавляет его в окно ключей (т. е. текущий вид) и после этого добавляет NavigationController.
Чтобы настроить связь с боковой панелью, я создал два протокола
- SidebarDelegate:
Делегат боковой панели - это основной протокол, с помощью которого вы узнаете, выбрал ли пользователь какой-либо ViewController или нет.
- NavigationDelegate:
этот протокол используется для связи между оболочкой и контроллером навигации. Когда пользователь нажимает любую кнопку. это сообщает классу обёртки об этом.
Класс-оболочка имеет метод closeSidebar , который затем закрывает боковую панель и сообщает классу Controller, что боковая панель закрыта с опцией.
В sidebarDidClose вы можете решить, что делать с выбором, сделанным пользователем.
Я немного торопился, поэтому я использовал Int , тогда как вы должны рассмотреть возможность использования struct или class, в зависимости от того, что вам нужно, чтобы определить, какой ViewController открыть.
https://github.com/sahilmanchanda2/SidebarTest