Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/ios/99.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ios 自定义UINavigationBar的外观_Ios_Swift_User Interface_Uikit - Fatal编程技术网

Ios 自定义UINavigationBar的外观

Ios 自定义UINavigationBar的外观,ios,swift,user-interface,uikit,Ios,Swift,User Interface,Uikit,我对iOS UI设计还不熟悉,我正在编写代码来显示高度定制的导航栏,这将用于我的交通应用程序 以下是我的导航栏的功能(请参见下图): Layout Margins为18,其子视图之间的Space为9 它的所有子视图“height都是44,所有UIBarButtonItem都是矩形 backBarButtonItem的位置应与leftBarButtonItem相同 在正常状态下,其高度为80 在展开状态下(例如地图应用程序中的方向字段视图),其标题视图将包含两个UITextFields,因此其高

我对iOS UI设计还不熟悉,我正在编写代码来显示高度定制的导航栏,这将用于我的交通应用程序

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

  • Layout Margins
    18
    ,其子视图之间的
    Space
    9
  • 它的所有子视图“
    height
    都是
    44
    ,所有
    UIBarButtonItem
    都是矩形
  • backBarButtonItem
    的位置应与
    leftBarButtonItem
    相同
  • 正常状态下,其
    高度
    80
  • 展开状态下(例如地图应用程序中的方向字段视图),其
    标题视图
    将包含两个
    UITextField
    s,因此其
    高度
    应为
    136
  • 查看真实设计截图 所以我已经声明了
    UINavigationBar
    的子类,并使用Identity Inspector将自定义类连接到故事板中的
    导航栏
    对象。然而,我不知道从哪里开始。虽然现在我重写了
    sizehatfits(usize:)
    函数以使其
    高度
    变长,但子视图接近底部。我找不到像谷歌地图、优步等定制
    UINavigationBar
    的最佳实践


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

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

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

  • 在自定义类中,执行以下操作

    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()中,添加以下代码以按需要提升标题(通常是!)

  • 现在,您可以根据需要设计一个视图(在这里,我已经用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) 
    
  • 因此,您可以这样子类化导航栏。但是,当您将任何其他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
    
        }
    }
    
    }

    }


  • 不建议使用子类化
    UINavigationBar
    。你应该探索
    UIAppearance
    类以获得所需的UI。我喜欢上面的设计截图,你是如何制作的?为什么不使用一个简单的视图并向其中添加所需的子视图?在我看来,这是做你想做的事情更简单有效的方法。@Adeel谢谢!但是,当我按下/弹出另一个导航项时,子视图仍保持不变。您可以共享屏幕截图或其他内容吗?
    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
        }