我是 iOS UI 设计的新手,我正在编写显示高度自定义导航栏的代码,我的交通应用程序将使用它。
这是我的导航栏的特点(见下图):
Layout Margins
为18
, subview 之间的Space
为9
。- 它的所有 subview 的
高度
都是44
,所有的UIBarButtonItem
都是矩形。 backBarButtonItem
的位置应与leftBarButtonItem
相同。- 在正常状态,它的
高度
是80
。 - 在展开状态(例如 map 应用中的方向字段 View ),其
titleView
将包含两个UITextField
s,所以它的高度
应该是136
。
查看真实设计截图
所以我声明了 UINavigationBar
的子类,并使用 Identity Inspector 将自定义类连接到 Storyboard中的 Navigation Bar
对象。但是,我不确定从哪里开始。虽然我暂时覆盖了 sizeThatFits(_ size:)
函数以使其 height
变长,但 subview 接近底部。我找不到自定义 UINavigationBar
的最佳实践,例如 Google map 、Uber 等。
如何通过子类化 UINavigationBar
来实现这样的导航栏?或者还有其他解决方案吗?
最佳答案
您可以通过以下步骤子类化 UINavigationBar..
添加一个新类(UINavigationBar 的子类),选择您的 ViewController 的 NavigationController。从 Document Outline 中选择 ViewController Navigation Bar。将类(class)设置为您的自定义类(class)。
在您的自定义类中,执行以下操作..
override func sizeThatFits(_ size: CGSize) -> CGSize { var bound = super.sizeThatFits(size) bound.height += sizeToAdd //The height you want return bound } override init(frame: CGRect) { super.init(frame: frame) self.setup() } required init?(coder aDecoder: NSCoder) { super.init(coder: aDecoder) self.setup() } override func layoutSubviews() { super.layoutSubviews() //If you don't override this function and do as follows, you'll //find that all NavigationButtons and the Title positioned at the //bottom of your navigation bar.(for the Title, we still need to //add one line in setup()) let classes = ["UIButton", "UINavigationItemView", "UINavigationButton"] for object in self.subviews{ let classOfObject = String(describing: type(of: object)) if classes.contains(classOfObject){ var objectFrame = object.frame objectFrame.origin.y -= self.sizeToAdd object.frame = objectFrame } } }
现在在 setup() 中,添加以下代码以根据需要提升标题(通常!)
func setup() -> Void { self.setTitleVerticalPositionAdjustment(-self.sizeToAdd, for: .default) }
现在,您可以根据需要设计一个 View (在这里,我已经使用 XIB 加载了一个自定义 View ,您也可以使用代码来完成。)并在您的 ViewController 中将其作为 subview 添加到您的导航栏.例如,在您的 viewDidLoad..
YOURVIEW.frame = CGRect(x: 0, y: 44, width: (self.navigationController?.navigationBar.bounds.width)!, height: (self.navigationController?.navigationBar.bounds.height)! + self.sizeToAdd)//The height self.navigationController?.navigationBar. addSubview(YOURVIEW)
因此,您可以通过这种方式对导航栏进行子类化。但是当你将任何其他 viewController 推到这个 viewController 上时,你会看到(如果你没有将另一个 NavigationController 嵌入到你正在推的 viewController 中) View 也保持在推送的 viewController 中。您可以在推送任何其他 viewController 之前将其从 super View 中删除。仅仅删除它不会提供良好的用户体验,因为其他系统元素(如果有的话)会很好地淡出。因此,请执行以下操作以提供良好的用户体验...
override func viewWillAppear(_ animated: Bool) { super.viewWillAppear(true) if(!(self.navigationController?.navigationBar.subviews.contains (YOURVIEW))!){ //Either get it working with setting a tag to //your view and checking it against all subviews //if you haven't use XIB self.navigationController?.navigationBar. addSubview(YOURVIEW) }else { UIView.transition(with: YOURVIEW, duration: 0.5, options: [ANYOPTIONS], animations: { self.profileNavigationView.alpha = 1.0 }) { (success) in } }
override func viewWillDisappear(_ animated: Bool) { super.viewWillDisappear(true) UIView.transition(with: YOURVIEW, duration: 0.5, options: [ANYOPTIONS], animations: { self.profileNavigationView.alpha = 0.0 }) { (success) in //remove it here if you want }
关于ios - 自定义 UINavigationBar 的外观,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42265627/