繁体   English   中英

使用hidesBarsOnSwipe更新ProgressView的约束

[英]Updating Constraints for ProgressView with hidesBarsOnSwipe

我试图在UINavigationBar内部显示进度条,如此处所述: 在UINavigationController的UINavigationBar内部或顶部显示UIProgressView

在Swift中完成后,自定义UINavigationController类如下所示:

class NavigationControllerWithProgress: UINavigationController {

    var progressView: UIProgressView!
    var progressBottomConstraint: NSLayoutConstraint!

    override func viewDidLoad() {
        super.viewDidLoad()

        hidesBarsOnSwipe = true
        hidesBarsWhenVerticallyCompact = true

        // adding ProgressView to UINavigationController to allow it to be placed inside the UINavigationBar
        // see: https://stackoverflow.com/questions/19211999/showing-a-uiprogressview-inside-or-on-top-of-a-uinavigationcontrollers-uinaviga
        progressView = UIProgressView(progressViewStyle: UIProgressViewStyle.Bar)
        view.addSubview(progressView)

        progressView.translatesAutoresizingMaskIntoConstraints = false
        progressView.setProgress(0.5, animated: false)

        progressBottomConstraint = NSLayoutConstraint(item: progressView, attribute: NSLayoutAttribute.Bottom, relatedBy: NSLayoutRelation.Equal, toItem: self.navigationBar, attribute: NSLayoutAttribute.Bottom, multiplier: 1, constant: -0.5)
        view.addConstraint(progressBottomConstraint)

        var constraint: NSLayoutConstraint

        constraint = NSLayoutConstraint(item: progressView, attribute: NSLayoutAttribute.Left, relatedBy: NSLayoutRelation.Equal, toItem: self.view, attribute: NSLayoutAttribute.Left, multiplier: 1, constant: 0)
        view.addConstraint(constraint)

        constraint = NSLayoutConstraint(item: progressView, attribute: NSLayoutAttribute.Right, relatedBy: NSLayoutRelation.Equal, toItem: self.view, attribute: NSLayoutAttribute.Right, multiplier: 1, constant: 0)
        view.addConstraint(constraint)
    }
}

问题:一旦UINavigationBar被OnSwipe / WhenVerticallyCompact自动隐藏,约束就会停止工作,即ProgressView被放到StatusBar下。

我试图在updateViewConstraints()和/或viewWillLayoutSubviews()中更新它,这是我目前唯一看到的方法。

由于常量已经用于相对于UINavigationBar分隔符的位置(请参见链接的SO线程),因此我尝试在这种情况下测试updateViewContraints():

override func updateViewConstraints() {
    super.updateViewConstraints()

    view.removeConstraint(progressBottomConstraint)
    progressBottomConstraint = NSLayoutConstraint(item: progressView, attribute: NSLayoutAttribute.Top, relatedBy: NSLayoutRelation.Equal, toItem: self.navigationBar, attribute: NSLayoutAttribute.Bottom, multiplier: 1, constant: 30)
    view.addConstraint(progressBottomConstraint)
}

注意此测试的常数设置为30。

通过这样做,我可以看到该约束在自动隐藏UINavigationBar时效果不佳:当隐藏/显示带有Rotation的导航栏(垂直紧凑时)或Swipe时,

  • 纵向时,UINavigationBar下30像素,但
  • 当UINavigationBar隐藏在横向视图中时
  • 当UINavigationBar以横向显示时不可见(覆盖)

有什么建议么?

尽管可以通过代码使用自动布局约束来执行此操作,但是使用组件(此处为SnapKit)可以使操作更加简单:

override func viewDidLoad() {
    super.viewDidLoad()

    [...]
    progressView.snp_makeConstraints { (make) -> Void in
        progressViewTopConstraint = make.top.equalTo(snp_topLayoutGuideBottom).offset(-2.5).constraint
        make.left.equalTo(view).offset(0)
        make.right.equalTo(view).offset(0)
    }
}

func updateProgressViewConstraint() {
    let navBarHeight = navigationBar.frame.size.height
    progressViewTopConstraint?.updateOffset(navigationBar.hidden ? 0 : navBarHeight - 2.5)
    view.bringSubviewToFront(progressView)
}

override func viewWillLayoutSubviews() {
    updateProgressViewConstraint()
    super.viewWillLayoutSubviews()
}

updateViewConstraints()是更好的重写方法,但是在这种情况下,新的hidesBarOnSwipe会出现问题(错误的progressView位置)。

注意:在UINavigationController中执行此操作时,progressView仍会跳转(即,在UINavigationBar完成过渡后设置的位置),因此我现在将其移至View本身。

编辑:将其放置在视图本身中可解决栏的跳跃问题,但当然不允许再将UIProgressView放在UINavigationBar内。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM