基于滚动视图缩小滚动条上的导航栏

时间:2018-12-25 22:15:53

标签: ios swift xcode-storyboard

我在View Controller中将滚动视图设置为固定高度。我想在顶部使用带有大标题的导航栏,因此当我滚动滚动视图时,它应该像在导航控制器中那样折叠。是否有可能做到这一点?我的场景看起来像这样:

Dashboard Scene Layout

导航栏具有上/左/右0约束,又是视图。当前,它正确地保持在顶部,但是不会按预期滚动折叠。

3 个答案:

答案 0 :(得分:1)

请勿使用这样的“松散”导航栏。即使您不打算进行任何导航,也请使用导航控制器。它免费为您提供所需的行为。

答案 1 :(得分:0)

最后,我创建了一个自定义视图来复制导航栏。在这里,您可以看到它的外观并阅读以下步骤进行复制:

enter image description here

  1. 要设置您的View Controller使其与自定义Scroll View一起使用,请首先确保您对控制器使用Freeform尺寸。为此,请在大小检查器中选择“自由格式”,然后将高度设置为新的“滚动视图”的高度:

    enter image description here

  2. 插入滚动视图并设置0个上/左/右/下约束,因此其大小将与您的View Controller相同:

    enter image description here

  3. 像往常一样将内容添加到滚动视图

  4. 现在要创建自定义导航栏,在“滚动视图”之外添加一个视图,并设置如下约束:

    enter image description here

    注意几件事:

    • 顶部约束与超级视图(而不是安全区域)对齐,因此视图位于状态栏后面
    • 高度设置为> = 44,因此它是最小高度,如果内容较大,则可以扩展
    • 在“属性”检查器上,选择“剪辑到边界”,这样视图内的内容就不会溢出(就像在CSS中一样,overflow:hidden)
    • 这时您可能会在Storyboard中看到一些错误,但不必担心:这是因为您的View中没有任何内容,而且它也不知道应该有多高
  5. 将“视图”背景设置为透明,并在内部添加“带有模糊效果的视觉效果视图”,并具有0个顶部/左侧/右侧/底部约束。这会模糊自定义导航栏后面的内容

  6. 现在,请确保在导航栏视图(位于约束设置上方)中选中“安全区域布局指南”复选框:

    enter image description here

    这样,您可以在视图内部添加不会位于状态栏后面的内容,因为它位于安全区域之外。它也可以使用该缺口。

  7. 在视图内添加标签,将“顶部和底部”约束设置为“安全区域”,并确保也定义了固定的高度约束:

    enter image description here

    现在您还可以看到情节提要中的错误都消失了:)此时,这就是所有内容的样子:

    enter image description here

  8. 现在是编码部分。在ViewController中,为ScrollView和自定义导航栏设置插座。为此,请切换到助手编辑器(维恩-图符号右上方),在情节提要中选择元素,按住CTRL并将其拖入ViewController类中

    enter image description here

    对作为导航栏的“视图”执行相同操作:

     @IBOutlet weak var mainScrollView: UIScrollView!
     @IBOutlet weak var customNavigationBar: UIView!
    
  9. 接下来,您需要在类中添加UIScrollViewDelegate,以便可以使用scrollViewDidScroll函数监听滚动事件并获取当前滚动偏移量的实际Y位置:

     class ViewController: UIViewController, UIScrollViewDelegate {
    

    您还需要在viewDidLoad挂钩中设置委托:

    mainScrollView.delegate = self
    
  10. 创建一个名为scrollViewDidScroll的新函数以获取滚动位置,您可以使用它与其他元素一起制作各种动画。在这种情况下,如果滚动位置达到44(这是我为自定义导航栏设置的高度),它将动画化为完全不透明:

    func scrollViewDidScroll(_ scrollView: UIScrollView) {
        let y = self.mainScrollView.contentOffset.y
        let barHeight = 44
    
        if(y < barHeight) {
            customNavigationBar.alpha = y/CGFloat(barHeight)
        } else {
            customNavigationBar.alpha = 1
        }
    }
    

    您可以使用相同的逻辑对导航栏中的标签进行动画处理,更改其大小等...

完整的ViewController:

class ViewController: UIViewController, UIScrollViewDelegate {
    @IBOutlet weak var mainScrollView: UIScrollView!
    @IBOutlet weak var customNavigationBar: UIView!

    override func viewDidLoad() {
        super.viewDidLoad()

        mainScrollView.delegate = self
        customNavigationBar.alpha = 0
    }

    func scrollViewDidScroll(_ scrollView: UIScrollView) {
        let y = self.mainScrollView.contentOffset.y
        let barHeight = 44

        if(y < 44) {
            customNavigationBar.alpha = y/CGFloat(barHeight)
        } else {
            customNavigationBar.alpha = 1
        }
    }

}

答案 2 :(得分:0)

func scrollViewDidScroll(_ scrollView: UIScrollView) {
        var height = CGFloat()
        if(scrollView.panGestureRecognizer.translation(in: scrollView.superview).y > 0) {
            height = 130
        }
        else {
            height = 44
        }
        UIView.animate(withDuration: 0.5) {
            self.navBarHeightConstraint?.constant = height
            self.view.layoutIfNeeded()
        }
    }