如何在UIToolbar上方显示UIView/UIControl且仅归属当前ViewController?
解决UIToolbar上方显示专属ViewController按钮的问题
你遇到的这个视图层级问题我之前也碰过——要让按钮只属于当前活跃的VC,同时稳稳显示在Toolbar上方,还不能被裁剪触摸区域,确实得选对视图层级和渲染顺序。给你几个可行的方案:
方案1:调整按钮的Z轴层级(最快见效)
你最初把按钮加在navigationController?.view的思路是对的,竖屏时被Toolbar盖住只是因为Toolbar的Z轴层级比你的按钮高。只需要手动把按钮的Z轴提上去就行:
// 初始化按钮 let addButton = UIButton(type: .custom) addButton.frame = CGRect(x: 0, y: 0, width: 48, height: 48) addButton.setBackgroundImage(UIImage(named:"Button - Add"), for: .normal) // 添加到导航控制器的视图,并提高Z轴层级 if let navView = self.navigationController?.view { navView.addSubview(addButton) addButton.layer.zPosition = navView.layer.zPosition + 1 }
这样按钮会留在当前导航控制器的视图层级里,不会跑到popover或模态VC的上面,而且不管横竖屏都能压在Toolbar之上。
方案2:添加到Toolbar的父视图(更稳妥)
有时候导航控制器的视图层级里,Toolbar会被放在特殊的子视图中,这时候可以把按钮加到Toolbar的父视图里,再确保按钮在视觉层级最上层:
if let toolbar = self.navigationController?.toolbar, let toolbarSuperview = toolbar.superview { let addButton = UIButton(type: .custom) addButton.frame = CGRect(x: 0, y: 0, width: 48, height: 48) addButton.setBackgroundImage(UIImage(named:"Button - Add"), for: .normal) // 把按钮加到Toolbar的父视图,再手动置顶 toolbarSuperview.addSubview(addButton) toolbarSuperview.bringSubviewToFront(addButton) }
这个方案能保证按钮和Toolbar在同一个视图层级,不会被其他无关视图干扰,而且按钮是独立的子视图,触摸区域完全不受Toolbar的边界限制。
方案3:自定义Toolbar布局(最规范的绑定方式)
如果上面两种方案有边缘场景不适用,你可以直接把按钮加到Toolbar里,但关闭Toolbar的边界裁剪:
if let toolbar = self.navigationController?.toolbar { let addButton = UIButton(type: .custom) // 让按钮向上偏移一半,露出Toolbar上方的部分 addButton.frame = CGRect(x: 0, y: -24, width: 48, height: 48) addButton.setBackgroundImage(UIImage(named:"Button - Add"), for: .normal) toolbar.addSubview(addButton) // 关键:关闭边界裁剪,让按钮超出Toolbar的部分也能响应触摸 toolbar.clipsToBounds = false }
这种方式适合需要按钮和Toolbar联动的场景,按钮和Toolbar的绑定更紧密,只要关掉clipsToBounds,触摸区域就不会被Toolbar的边界切掉。
顺便说下你之前尝试踩的坑:
- 加在
navigationController?.view但没调Z轴:竖屏时Split View的渲染逻辑会让Toolbar的Z轴更高,所以按钮被盖住了。 - 加在全局window:这个window是应用最顶层的容器,所有VC都在它上面,自然会覆盖popover和模态窗口。
- 加在Toolbar但没关
clipsToBounds:Toolbar默认会把子视图裁剪到自身边界,所以按钮超出的部分触摸无效。
内容的提问来源于stack exchange,提问作者Dialogue
相关产品推荐
相关产品推荐

