自定义UINavigationBar的外观

时间:2017-02-16 05:24:19

标签: ios swift user-interface uikit

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

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

  1. Layout Margins18,其子视图之间的Space9
  2. 其所有子视图“height均为44,所有UIBarButtonItem均为矩形。
  3. backBarButtonItem的位置应与leftBarButtonItem相同。
  4. 正常状态时,其height80
  5. 展开状态,例如地图应用中的方向字段视图)中,其titleView将包含两个UITextField,因此其{ {1}}应为height
  6. 请参阅Real Design Screenshots See Real Design Screenshots 所以我已经声明了136的子类,并使用Identity Inspector将自定义类连接到故事板中的UINavigationBar对象。但是,我不知道从哪里开始。虽然我现在超越Navigation Bar函数使其sizeThatFits(_ size:)长,但是子视图接近底部。我找不到自定义height的最佳做法,例如谷歌地图,优步等。

    如何通过继承UINavigationBar来实现此类导航栏?或者还有其他解决方案吗?

1 个答案:

答案 0 :(得分:2)

您可以使用以下步骤继承UINavigationBar ..

  1. 添加一个新类(UINavigationBar的子类),选择ViewController的NavigationController。从文档大纲中选择ViewController导航栏。将班级设置为自定义班级。

  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
        }
    

    }