QQ 抽屉样式左右侧滑菜单-QDrawerController
之前项目中实现抽屉样式左右侧滑菜单都是在使用 MMDrawerController,一个轻量、使用简单的框架,向经典致敬!
在重构老项目时要使用 swift 语言,就想着用swift实现这个这功能,在学习了 MMDrawerController 源码和一些博客文章,决定动手。
实现思路
- 在 QDrawerController 中使用 addChildViewController 方法,添加左中右三个ViewController并调整响应初始坐标位置。
图层顺序:window -> QNavigationController -> leftViewController ->centerViewController -> rightViewController - QNavigationController view 添加边缘侧滑手势,以手势滑动的值控制页面的 x 轴。
- centerViewController 添加遮罩层,透明度根据手势滑动值控制
效果
上图- 效果还可以,由于使用 QDrawerController 为基础层,会影响到 StatusBar 的自定义设置,所以需要 childViewControllerForStatusBarStyle 返回对应的 ViewController,
// MARK: - 状态栏变化处理 ******************
enum QDrawerSide {
case none
case left
case right
}
private var openSide: QDrawerSide? = QDrawerSide.none {
didSet{
setNeedsStatusBarAppearanceUpdateIfSupported()
}
}
override var childViewControllerForStatusBarStyle: UIViewController? {
return getTopViewController()
}
override var childViewControllerForStatusBarHidden: UIViewController? {
return getTopViewController()
}
private func childViewControllerForSide(drawerSide: QDrawerSide) -> UIViewController {
switch drawerSide {
case .left:
return leftDrawerVC!
case .right:
return rightDrawerVC!
case .none:
return centerVC!
}
}
private func setNeedsStatusBarAppearanceUpdateIfSupported() {
if responds(to: #selector(setNeedsStatusBarAppearanceUpdate)) {
self.perform(#selector(setNeedsStatusBarAppearanceUpdate))
}
}
private func getTopViewController() -> UIViewController {
if self.childViewControllerForSide(drawerSide: openSide!) == centerVC {
if centerVC is UITabBarController {
for vcs in (centerVC?.childViewControllers)! {
if vcs is UINavigationController {
return (vcs as! UINavigationController).topViewController!
} else {
return vcs
}
}
} else if centerVC is UINavigationController {
return (centerVC as! UINavigationController).topViewController!
} else {
return self.childViewControllerForSide(drawerSide: openSide!)
}
}
return self.childViewControllerForSide(drawerSide: openSide!)
}
完美解决 StatusBar 的自定义设置。因为使用了几个手势,所以需要特别处理一下手势的冲突问题(就不上代码了,看源码吧)。
使用
使用起来很简单
初始化方法
init(centerVC: UIViewController, leftDrawerVC: UIViewController, maxLeftDrawerWidth: CGFloat)
init(centerVC: UIViewController, rightDrawerVC: UIViewController, maxRightDrawerWidth: CGFloat)
init(centerVC: UIViewController, leftDrawerVC: UIViewController, maxLeftDrawerWidth: CGFloat, rightDrawerVC: UIViewController, maxRightDrawerWidth: CGFloat)
设置 centerViewController
open func setCenterVC(newCenterVC: UIViewController)
跳转到某个页面
open func didSelectedVC(didSelectedVC: UIViewController)
打开左侧页面
open func openLeftDrawer()
打开右侧页面
open func openRightDrawer()
- 给 UIViewController 增加了 extension ,方便调用打开侧页面方法
// MARK: - UIViewController 扩展,方便调用 QDrawerController
extension UIViewController {
var q_drawerController: QDrawerController {
var drawerController: QDrawerController?
var parentVC = self.parent
while parentVC != nil {
if parentVC is QDrawerController {
drawerController = parentVC as? QDrawerController
}
parentVC = parentVC?.parent
}
return drawerController!
}
}
// 使用时如下
self.q_drawerController.openRightDrawer()
self.q_drawerController.setCenterVC(newCenterVC: UIStoryboard(name: "Main", bundle: nil).instantiateInitialViewController()!)
self.q_drawerController.setCenterVC(newCenterVC: BViewController())
self.q_drawerController.didSelectedVC(didSelectedVC: CViewController())
结语
QDrawerController 也很简单,目前测试检测未发现 Bug,但肯定会有考虑不周之处,请朋友们多多指正。
奉上源码地址 QDrawerController