[英]How do I incorporate a slide out/burger menu to an existing tab bar controller
所以我想创建一个滑出菜单。 我希望菜单在触摸选项卡栏项目/按钮时滑出。 到目前为止,我已经创建了一个带有 4 个不同选项卡栏按钮的选项卡视图控制器。 每个按钮通向不同的视图控制器,并且每个视图控制器都被分离到它们自己的故事板中。
我尝试将侧边菜单的 UIViewController 添加到已经建立为 UITabBarController 的类中,但出现错误:
从类“UITabBarController”和“UIViewController”的多重继承。
有没有解决的办法?
我感谢所有的帮助
应用程序往往有一个顶级容器,比如无法嵌入到视图中的Tab Bar Controller
。 这里的方法是将主体和左侧菜单分别包装在Container View
。 现在这两个元素都可以安排在包装器View Controller
。
Scroll View
用于通过在屏幕上/屏幕外移动左侧菜单来模拟打开和关闭菜单。
将View Controller
拖放到情节提要上。 这是您进入应用程序的入口点。 选中Is Initial View Controller
复选框。 将Simulated Size
从Fixed
更改为Freeform
。 将宽度设置为 568,这样我们就可以并排放置菜单和标签栏。 创建一个新的 Swift 文件并将此视图控制器的类设置为 ContainerVC。
import UIKit
class ContainerVC : UIViewController {
}
在 Container View Controller 中,放入一个Scroll View
并在所有方向上添加约束。
选中Scrolling Enabled
复选框。 这允许您平移屏幕以滑动菜单。 如果您的应用使用水平滚动元素,您可能需要禁用此功能。
选中Paging Enabled
复选框。 这会将菜单捕捉到打开或关闭状态。
取消选中Bounces
框。 您真的不想滚动超过 Tab Bar Controller 的右边缘。
将 IBOutlet 连接到 ContainerVC:
@IBOutlet weak var scrollView: UIScrollView!
左边的容器包含菜单,并不完全是屏幕的整个宽度。
将Container View
拖到Scroll View
的左侧。
将顶部、左侧和右侧的约束添加到包含的Scroll View
。
将宽度硬编码为 260。
使用 ContainerVC 的嵌入视图为Equal height
添加约束。 注意:不要限制滚动视图的高度。 删除Container View
附带的嵌入式View Controller
。
将一个新的Table View Controller
(根据您的需要的任何视图)放到故事板上,并使用嵌入转场进行连接。
正确的容器包含应用程序的主体,即Tab Bar Controller
。
将第二个Container View
拖到Scroll View
的右侧。
向包含Scroll View
的顶部、右侧和底部添加约束。 水平连接到您之前创建的左侧容器视图。
将Equal height
和Equal width
为 ContainerVC 的嵌入视图。
注意:不要将这些限制在滚动视图中。
再次,删除随Container View
免费提供的嵌入式视图控制器。 相反,创建一个embed
到Tab Bar Controller
segue。
要在两个容器之间创建一点视觉分离,请将Runtime Attribute
添加到右侧容器。 添加layer.shadowOpacity
的数字为0.8
。
将每个选项卡嵌入到Navigation Controller
。 这样做会为您提供一个免费的Navigation Bar
。
将一个Bar Button Item
拖到每个Navigation Bar
左上角。
将IBAction
到每个控制器。 这些将向曾祖父ContainerVC
发出Notification
以切换菜单。
@IBAction func toggleMenu(sender: AnyObject) {
NotificationCenter.default().post(name: Notification.Name("toggleMenu"), object: nil)
}
最后将以下代码添加到 ContainerVC 中:
class ContainerVC : UIViewController {
// This value matches the left menu's width in the Storyboard
let leftMenuWidth:CGFloat = 260
// Need a handle to the scrollView to open and close the menu
@IBOutlet weak var scrollView: UIScrollView!
override func viewDidLoad() {
// Initially close menu programmatically. This needs to be done on the main thread initially in order to work.
DispatchQueue.main.async() {
self.closeMenu(animated: false)
}
// Tab bar controller's child pages have a top-left button toggles the menu
NotificationCenter.default.addObserver(self, selector: #selector(ContainerVC.toggleMenu), name: NSNotification.Name(rawValue: "toggleMenu"), object: nil)
NotificationCenter.default.addObserver(self, selector: #selector(ContainerVC.closeMenuViaNotification), name: NSNotification.Name(rawValue: "closeMenuViaNotification"), object: nil)
// Close the menu when the device rotates
NotificationCenter.default.addObserver(self, selector: #selector(ContainerVC.rotated), name: NSNotification.Name.UIDeviceOrientationDidChange, object: nil)
// LeftMenu sends openModalWindow
NotificationCenter.default.addObserver(self, selector: #selector(ContainerVC.openModalWindow), name: NSNotification.Name(rawValue: "openModalWindow"), object: nil)
}
// Cleanup notifications added in viewDidLoad
deinit {
NotificationCenter.default.removeObserver(self)
}
@objc func openModalWindow() {
performSegue(withIdentifier: "openModalWindow", sender: nil)
}
@objc func toggleMenu() {
scrollView.contentOffset.x == 0 ? closeMenu() : openMenu()
}
// This wrapper function is necessary because closeMenu params do not match up with Notification
@objc func closeMenuViaNotification(){
closeMenu()
}
// Use scrollview content offset-x to slide the menu.
func closeMenu(animated:Bool = true){
scrollView.setContentOffset(CGPoint(x: leftMenuWidth, y: 0), animated: animated)
}
// Open is the natural state of the menu because of how the storyboard is setup.
func openMenu(){
print("opening menu")
scrollView.setContentOffset(CGPoint(x: 0, y: 0), animated: true)
}
@objc func rotated(){
if UIDeviceOrientationIsLandscape(UIDevice.current.orientation) {
DispatchQueue.main.async() {
print("closing menu on rotate")
self.closeMenu()
}
}
}
}
extension ContainerVC : UIScrollViewDelegate {
func scrollViewDidScroll(_ scrollView: UIScrollView) {
print("scrollView.contentOffset.x:: \(scrollView.contentOffset.x)")
}
func scrollViewWillBeginDragging(_ scrollView: UIScrollView) {
scrollView.isPagingEnabled = true
}
func scrollViewDidEndDecelerating(_ scrollView: UIScrollView) {
scrollView.isPagingEnabled = false
}
}
该代码实现了以下功能:
希望您有一个简单的滑出式左侧菜单,可以在其上构建应用程序的其余部分。
不要使用 UITabBarController,并使用一个视图控制器和按钮操作来管理选项卡控件。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.