我为这个问题创建了一个示例项目。您可以在上图中看到输出。基本上我所做的是在侧边栏周围创建了一个包装类,然后我可以随时使用它:)
侧边栏
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)
}
}
导航控制器
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)
}
}
视图控制器
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,然后将其添加到 keywindow(即您当前的视图),然后添加 NavigationController。
为了设置与侧边栏的通信,我创建了两个协议
- SidebarDelegate:
侧边栏委托是主要协议,您可以通过它了解用户是否选择了任何 ViewController。
- 导航委托:
该协议用于包装器和导航控制器之间的通信。当用户点击任何按钮时。它通知包装类。
包装类有一个方法 closeSidebar 然后关闭侧边栏并通知控制器类侧边栏关闭选项。
在 sidebarDidClose 中,您可以决定如何处理用户所做的选择。
我有点着急,这就是我使用 Int 的原因,而您应该考虑使用适合您需要的结构或类来确定要打开哪个 ViewController。
https://github.com/sahilmanchanda2/SidebarTest