【问题标题】:Customize appearance of UINavigationBar自定义 UINavigationBar 的外观
【发布时间】:2017-07-05 01:45:06
【问题描述】:

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

以下是我的导航栏的功能(见下图):

  1. Layout Margins18,其子视图之间的Space9
  2. 其所有子视图的height 均为44,且所有UIBarButtonItem 均为矩形。
  3. backBarButtonItem 的位置应与 leftBarButtonItem 相同。
  4. 正常状态,其height80
  5. 展开状态如地图应用程序中的方向字段视图),它的titleView将包含两个UITextFields,所以它的height应该是136

查看真实设计截图 所以我声明了UINavigationBar 的子类,并使用身份检查器将自定义类连接到情节提要中的Navigation Bar 对象。但是,我不确定从哪里开始。尽管我暂时覆盖了sizeThatFits(_ size:) 函数以使其height 长,但子视图接近底部。我找不到自定义 UINavigationBar 的最佳做法,例如 Google 地图、Uber 等。

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

【问题讨论】:

  • 不推荐子类化UINavigationBar。您应该探索UIAppearance 类以获得所需的用户界面。
  • 我喜欢你上面的设计截图,你是怎么做到的?
  • 你为什么不直接使用一个简单的视图并在其中添加想要的子视图呢?在我看来,这是做你想做的事情的更简单有效的方法。
  • @Adeel 谢谢!但是,当我按下/弹出另一个导航项时,子视图仍然存在。
  • 能分享一下截图什么的吗?

标签: ios swift user-interface uikit


【解决方案1】:

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

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

  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. 现在,您可以根据需要设计一个视图(这里,我已经使用 XIB 加载了一个自定义视图,您也可以使用代码来完成。)并在您的 ViewController 中作为子视图添加到您的导航栏。例如,在您的 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 推送到这个视图控制器上时,您会看到(如果您没有将另一个 NavigationController 嵌入到您正在推送的 viewController 中)该视图也保持在推送的 viewController 中。您可以在推送任何其他 viewController 之前将其从超级视图中删除。仅仅移除它不会提供良好的用户体验,因为其他系统元素(如果有的话)会很好地淡出。因此,请执行以下操作以提供良好的用户体验...

    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
        }
    

    }

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-11-23
    • 2015-04-07
    • 2014-03-06
    • 2011-08-25
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多