ios - 自定义 UINavigationBar 的外观

标签 ios swift user-interface uikit

我是 iOS UI 设计的新手,我正在编写显示高度自定义导航栏的代码,我的交通应用程序将使用它。

这是我的导航栏的特点(见下图): Custom UINavigationBar Blueprint

  1. Layout Margins18, subview 之间的 Space9
  2. 它的所有 subview 的高度都是44,所有的UIBarButtonItem都是矩形。
  3. backBarButtonItem 的位置应与 leftBarButtonItem 相同。
  4. 正常状态,它的高度80
  5. 展开状态(例如 map 应用中的方向字段 View ),其titleView 将包含两个UITextFields,所以它的高度应该是136

查看真实设计截图 See Real Design Screenshots 所以我声明了 UINavigationBar 的子类,并使用 Identity Inspector 将自定义类连接到 Storyboard中的 Navigation Bar 对象。但是,我不确定从哪里开始。虽然我暂时覆盖了 sizeThatFits(_ size:) 函数以使其 height 变长,但 subview 接近底部。我找不到自定义 UINavigationBar 的最佳实践,例如 Google map 、Uber 等。

如何通过子类化 UINavigationBar 来实现这样的导航栏?或者还有其他解决方案吗?

最佳答案

您可以通过以下步骤子类化 UINavigationBar..

  1. 添加一个新类(UINavigationBar 的子类),选择您的 ViewController 的 NavigationController。从 Document Outline 中选择 ViewController Navigation Bar。将类(class)设置为您的自定义类(class)。

  2. 在您的自定义类中,执行以下操作..

    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
            }
        }
    
    }
    
  3. 现在在 setup() 中,添加以下代码以根据需要提升标题(通常!)

    func setup() -> Void {
        self.setTitleVerticalPositionAdjustment(-self.sizeToAdd, for: 
        .default)
    }
    
  4. 现在,您可以根据需要设计一个 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) 
    
  5. 因此,您可以通过这种方式对导航栏进行子类化。但是当你将任何其他 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/

相关文章:

ios - 弹出 View Controller 在 Xcode 11.2.1 中打开后立即关闭

ios - 从使用 Titanium Appcelerator 创建的应用程序中删除灰色调

ios - Swift - 在展开可选值时意外发现 nil - 从委托(delegate)调用变量

java - 为什么在 Java SWT Selection 监听器中新创建的元素无法显示/触发绘制事件?

python - tkinter:更改特定菜单项的前景色

iOS 判断触摸次数

iphone - 我应该如何将 UIImages 存储在我的核心数据数据库中?

swift - 如何通过 CKRecordID 获取 AppleID?

ios - 将 google direction JSON 字符串 url 转换为 URL

内容顶部的 IOS 键盘建议栏