目前我有一个标准的标签栏,点击后会转到相应的视图控制器。But I want to make a menu pop out from tab bar when more tab is selected, as shown in below image.
有什么建议可以实施吗?提前致谢。
我建议你这样做:
首先,您应该考虑标签栏中可能存在的所有标签类型。在您的屏幕截图上有显示控制器的选项卡和显示菜单的选项卡。所以我们可以创建所有这些类型的枚举:
enum TabType {
case controller
case menu
}
之后,您可以存储选项卡类型的数组,以便它们在选项卡栏中显示,对于您的屏幕截图,如下所示
let tabTypes: [TabType] = [.controller, .controller, .controller, .controller, .menu]
然后你应该实现UITabBarControllerDelegate
'sfunc tabBarController(_:, shouldSelect:) -> Bool
方法,true
如果允许标签栏选择传递的控制器,则返回,false
否则返回。
如果您返回true
所有其他工作(例如呈现视图控制器和其他东西),标签栏控制器将为您完成。
在您的情况下,您想在选项卡单击时执行自定义操作,因此您应该返回false
. 在返回之前,您应该出示您的菜单。
func tabBarController(_ tabBarController: UITabBarController, shouldSelect viewController: UIViewController) -> Bool {
if let index = tabBarController.viewControllers?.index(of: viewController),
index < tabBarTypes.count {
let type = tabBarTypes[index]
switch type {
case .menu:
// perform your menu presenting here
return false
case .controller:
// do nothing, just return true, tab bar will do all work for you
return true
}
}
return true
}
在这个实现中,您可以轻松更改选项卡类型的顺序或添加一些其他选项卡类型并进行适当的处理。
根据我的理解,您想要的是,选择选项卡 1 并且用户转到选项卡 5,然后背景将是选项卡 1,反之亦然选项卡 2、3 和 4,并且应该弹出像您的图像所示的按钮. 如果我错了,请纠正我。
为此,您必须在用户浏览选项卡时捕获图像。
请在AppDelegate中找到以下代码,
var currentImage: UIImage! //It will be public variable
标签栏委托方法,
func tabBarController(_ tabBarController: UITabBarController, didSelect viewController: UIViewController) {
if tabBarController.selectedIndex == 4 {
let moreVC = tabBarController.selectedViewController as! MoreVC
moreVC.currentImage = currentImage
}
}
func tabBarController(_ tabBarController: UITabBarController, shouldSelect viewController: UIViewController) -> Bool {
if tabBarController.selectedIndex != 4 {
let navController = tabBarController.selectedViewController as! UINavigationController
let viewController = navController.viewControllers.last
currentImage = Common.imageWithView(inView: (viewController?.navigationController?.view)!) //UIImage(view: (viewController?.navigationController?.view)!)
}
return true
}
在这里,我将静态 4 作为最后一个选项卡索引,而 MoreVC 将是选项卡索引 4 的关联 ViewController。
从视图中获取图像的通用类,
class Common {
static func imageWithView(inView: UIView) -> UIImage? {
UIGraphicsBeginImageContextWithOptions(inView.bounds.size, inView.isOpaque, 0.0)
defer { UIGraphicsEndImageContext() }
if let context = UIGraphicsGetCurrentContext() {
inView.layer.render(in: context)
let image = UIGraphicsGetImageFromCurrentImageContext()
return image
}
return nil
}
}
请找MoreVC,
@IBOutlet weak var imageView: UIImageView!
var currentImage: UIImage! {
didSet {
imageView.image = currentImage
}
}
请在下面找到 MoreVC 故事板的图片。看起来它不像所有其他 ViewController 那样包含 NavigationController。
如有任何疑问,请告诉我。
这是对 Apples HIG 中 UI 模式布局的滥用。具体来说:
严格使用标签栏进行导航。不应使用标签栏按钮来执行操作。如果您需要提供作用于当前视图中的元素的控件,请改用工具栏。
此控件应用于扁平化您的应用层次结构。在这种情况下,您似乎正在混合按钮的功能。有时它会选择一个单独的视图控制器,有时它会显示一个动作列表。这对用户来说是一个令人困惑的情况,应该避免。
实现此目的并仍坚持 HIG 的一种方法是使用导航栏或工具栏。将此控件嵌入工具栏按钮中。最简单的情况是调用 aUIActionController
并.actionSheet
选择样式。
您可以使用可滚动的选项卡视图来获得更好的 UI,而不是显示菜单。如果您更喜欢使用库,这里有一个简单的可滚动标签栏,您可以实现。
1) 创建一个“Tab5ViewController”并使用它:
static func takeScreenshot(bottomPadding padding: CGFloat = 0) -> UIImage? {
let layer = UIApplication.shared.keyWindow!.layer
let scale = UIScreen.main.scale
UIGraphicsBeginImageContextWithOptions(CGSize(width: layer.frame.size.width, height: layer.frame.size.height - padding), false, scale)
guard let context = UIGraphicsGetCurrentContext() else { return nil }
layer.render(in: context)
let screenshot = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
return screenshot
}
使用屏幕截图作为“Tab5ViewController”的背景图片
2)在您的“Tab5ViewController”中,您可以拥有堆栈组件(附加选项卡),然后根据选择添加/删除子视图控制器
3) 修复边缘情况(如选项卡选择突出显示等......)
它的用户界面不好,但如果你愿意的话。
首先,您必须实现 UITabbarControllerDelegate 的委托方法,如下所示
func tabBarController(_ tabBarController: UITabBarController, shouldSelect
viewController: UIViewController) -> Bool {
if viewController.classForCoder == moreViewController.self
{
let popvc = MoreSubMenuViews(nibName: "MoreSubMenuViews", bundle: Bundle.main)
self.addChildViewController(popvc)
let tabbarHeight = tabBar.frame.height
let estimatedWidth:CGFloat = 200.0
let estimatedHeight:CGFloat = 300.0
popvc.view.frame = CGRect(x:self.view.frame.width - estimatedWidth, y: self.view.frame.height - estimatedHeight - tabbarHeight, width: estimatedWidth, height: estimatedHeight)
self.view.addSubview(popvc.view)
popvc.didMove(toParentViewController: self)
print("sorry stop here")
return true // if you want not to select return false here
}else{
//remove popup logic here if opened
return true
}
}
这里moreViewController是最后一个选项卡控制器,而 MoreSubMenuViews是 nib/xib 文件,其中包含图像中显示的按钮。