【问题标题】:hidesBarsOnSwipe never shows navbar again when scrolling uphidesBarsOnSwipe 向上滚动时不再显示导航栏
【发布时间】:2014-12-27 19:53:29
【问题描述】:

所以我想在向下滚动时隐藏导航栏并在向上滚动时将其恢复。隐藏它与

完美配合
self.navigationController?.hidesBarsOnSwipe = true

但我希望它在向上滚动时再次显示。我做了一个测试项目,其中视图控制器只有一个覆盖整个屏幕的 UICollectionView。然后按预期再次显示导航栏,直到我将此行添加到 viewDidLoad (将单元格添加到集合视图):

self.collectionView.delegate = self

这就是整个视图控制器的样子

class ViewController: UIViewController,UICollectionViewDataSource, UICollectionViewDelegate {

@IBOutlet var collectionView: UICollectionView!
override func viewDidLoad() {
    super.viewDidLoad()
    self.collectionView.dataSource = self
    self.collectionView.delegate = self
    self.collectionView.registerClass(UICollectionViewCell.self, forCellWithReuseIdentifier: "Test")
    self.navigationController?.hidesBarsOnSwipe = true
}

func collectionView(collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
    return 3
}

func numberOfSectionsInCollectionView(collectionView: UICollectionView) -> Int {
    return 1
}

func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {
    return collectionView.dequeueReusableCellWithReuseIdentifier("Test", forIndexPath: indexPath) as UICollectionViewCell
}

func collectionView(collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAtIndexPath indexPath: NSIndexPath) -> CGSize {
    return CGSizeMake(300, 300)
}
}

那么,当我将单元格添加到我的集合视图时,为什么显示导航栏会停止工作?

【问题讨论】:

    标签: objective-c swift ios8


    【解决方案1】:

    要使hidesBarsOnSwipe 正常工作,您的视图控制器的view 必须只包含UITableView 实例,不能包含其他任何内容。

    【讨论】:

      【解决方案2】:

      我尝试在 ViewDidLoad 函数中的 ViewController 类中将 hidesBarsOnSwipe 属性设置为 true,如下所示,但它无法处理在向上滑动时隐藏导航栏和在向下滑动时取消隐藏导航栏。

      class ViewController: UIViewController {
      
         override func viewDidLoad() {
            super.viewDidLoad()
            self.navigationController?.hidesBarsOnSwipe = true
         }
      }
      

      hidesBarsOnSwipe 设置为 true 仅当我们使用 UITableViewController 或 UICollectionViewController 作为主屏幕时才会生效,如果我们将 UITableView 添加到 UIViewController,hidesBarsOnSwipe 将不起作用用于显示数据列表。

      解决方案

      class TestTableViewController: UITableViewController {
      
          override func viewDidLoad() {
             super.viewDidLoad()
             self.navigationController?.hidesBarsOnSwipe = true
          }
      }
      

      希望这个答案可能会有所帮助...!

      【讨论】:

        【解决方案3】:

        我有同样的问题。当我添加隐藏状态栏和导航栏的代码时,它起作用了。

        - (BOOL)prefersStatusBarHidden {
          return self.navigationController.isNavigationBarHidden;
        }
        

        【讨论】:

        • 这行得通,但如果我不假装将状态栏隐藏在一起,则行不通。
        【解决方案4】:

        根据之前的 cmets - 这似乎是 ios 10.3 的错误

        当您使用 uicollectionview - 我提请您注意我从 APDynamicHeaderTableViewController 重新编写的一些代码 https://github.com/aaronpang/APDynamicHeaderTableViewController/issues/4

        它正在使用 snapkit https://github.com/SnapKit/SnapKit

        (向所有 IB + NSLayout 约束爱好者道歉。)

        class APDynamicHeaderTableViewController : UIViewController {
        
          var largeWideSize = CGSize(width: UIScreen.main.bounds.width , height: 285 )
          let headerView = APDynamicHeaderView () // Change your header view here
        
          let cellLayout: UICollectionViewFlowLayout = UICollectionViewFlowLayout()
          var feedCV:UICollectionView!
        
          fileprivate var headerViewHeight:CGFloat = 80 // this will be updated by scrolling
          fileprivate var headerBeganCollapsed = false
          fileprivate var collapsedHeaderViewHeight : CGFloat = UIApplication.shared.statusBarFrame.height
          fileprivate var expandedHeaderViewHeight : CGFloat = 100
          fileprivate var headerExpandDelay : CGFloat = 100
          fileprivate var tableViewScrollOffsetBeginDraggingY : CGFloat = 0.0
        
        
          init(collapsedHeaderViewHeight : CGFloat, expandedHeaderViewHeight : CGFloat, headerExpandDelay :CGFloat) {
            self.collapsedHeaderViewHeight = collapsedHeaderViewHeight
            self.expandedHeaderViewHeight = expandedHeaderViewHeight
            self.headerExpandDelay = headerExpandDelay
            super.init(nibName: nil, bundle: nil)
        
        
          }
        
        
          init () {
            super.init(nibName: nil, bundle: nil)
        
          }
        
          required init(coder aDecoder: NSCoder) {
            fatalError("init(coder:) has not been implemented")
          }
        
          override func loadView() {
            super.loadView()
            self.view.backgroundColor = .green
        
            // Cell Layout Sizes
            cellLayout.scrollDirection = .vertical
            cellLayout.sectionInset = UIEdgeInsets(top: 0, left: 10, bottom: 0, right: 10)
            cellLayout.itemSize = CGSize(width: UIScreen.main.bounds.width, height: 185 + 80)
        
        
            // Header view
            self.view.addSubview(headerView)
            headerView.snp.remakeConstraints { (make) -> Void in
                make.top.left.equalToSuperview()
                make.width.equalToSuperview()
                make.height.equalTo(headerViewHeight)
            }
        
            // CollectionView
            feedCV = UICollectionView(frame: .zero, collectionViewLayout: cellLayout)
            self.view.addSubview(feedCV)
            self.feedCV.snp.remakeConstraints { (make) -> Void in
                make.top.equalTo(headerView.snp.bottom) // this is pegged to the header view which is going to grow in height
                make.left.equalToSuperview()
                make.width.equalToSuperview()
                make.bottom.equalToSuperview()
            }
        
        
        
            feedCV.backgroundColor = .red
            feedCV.showsVerticalScrollIndicator = true
            feedCV.isScrollEnabled = true
            feedCV.bounces = true
            feedCV.delegate = self
            feedCV.dataSource = self
        
             // YOUR COLLECTIONVIEW CELL HERE!!!!!
            feedCV.register(VideoCollectionViewCell.self, forCellWithReuseIdentifier: VideoCollectionViewCell.ID)
        
        
          }
        
          // Animate the header view to collapsed or expanded if it is dragged only partially
          func animateHeaderViewHeight () -> Void {
            Logger.verbose("animateHeaderViewHeight")
        
            var headerViewHeightDestinationConstant : CGFloat = 0.0
            if (headerViewHeight < ((expandedHeaderViewHeight - collapsedHeaderViewHeight) / 2.0 + collapsedHeaderViewHeight)) {
              headerViewHeightDestinationConstant = collapsedHeaderViewHeight
            } else {
              headerViewHeightDestinationConstant = expandedHeaderViewHeight
            }
        
            if (headerViewHeight != expandedHeaderViewHeight && headerViewHeight != collapsedHeaderViewHeight) {
              let animationDuration = 0.25
              UIView.animate(withDuration: animationDuration, animations: { () -> Void in
                self.headerViewHeight = headerViewHeightDestinationConstant
                let progress = (self.headerViewHeight - self.collapsedHeaderViewHeight) / (self.expandedHeaderViewHeight - self.collapsedHeaderViewHeight)
                self.headerView.expandToProgress(progress)
                self.view.layoutIfNeeded()
              })
            }
          }
        }
        
        extension APDynamicHeaderTableViewController : UICollectionViewDelegate {
        
        }
        
        extension APDynamicHeaderTableViewController : UIScrollViewDelegate {
          func scrollViewWillBeginDragging(_ scrollView: UIScrollView) {
            // Clamp the beginning point to 0 and the max content offset to prevent unintentional resizing when dragging during rubber banding
            tableViewScrollOffsetBeginDraggingY = min(max(scrollView.contentOffset.y, 0), scrollView.contentSize.height - scrollView.frame.size.height)
        
            // Keep track of whether or not the header was collapsed to determine if we can add the delay of expansion
            headerBeganCollapsed = (headerViewHeight == collapsedHeaderViewHeight)
          }
        
          func scrollViewDidScroll(_ scrollView: UIScrollView) {
            // Do nothing if the table view is not scrollable
            if feedCV.contentSize.height < feedCV.bounds.height {
              return
            }
            var contentOffsetY = feedCV.contentOffset.y - tableViewScrollOffsetBeginDraggingY
            // Add a delay to expanding the header only if the user began scrolling below the allotted amount of space to actually expand the header with no delay (e.g. If it takes 30 pixels to scroll up the scrollview to expand the header then don't add the delay of the user started scrolling at 10 pixels)
            if tableViewScrollOffsetBeginDraggingY > ((expandedHeaderViewHeight - collapsedHeaderViewHeight) + headerExpandDelay) && contentOffsetY < 0 && headerBeganCollapsed {
              contentOffsetY = contentOffsetY + headerExpandDelay
            }
            // Calculate how much the header height will change so we can readjust the table view's content offset so it doesn't scroll while we change the height of the header
            let changeInHeaderViewHeight = headerViewHeight - min(max(headerViewHeight - contentOffsetY, collapsedHeaderViewHeight), expandedHeaderViewHeight)
            headerViewHeight = min(max(headerViewHeight - contentOffsetY, collapsedHeaderViewHeight), expandedHeaderViewHeight)
            let progress = (headerViewHeight - collapsedHeaderViewHeight) / (expandedHeaderViewHeight - collapsedHeaderViewHeight)
        //    Logger.verbose("headerViewHeight:",headerViewHeight)
            headerView.expandToProgress(progress)
            headerView.snp.updateConstraints { (make) -> Void in
                make.height.equalTo(headerViewHeight)
            }
        
            // When the header view height is changing, freeze the content in the table view
            if headerViewHeight != collapsedHeaderViewHeight && headerViewHeight != expandedHeaderViewHeight {
                feedCV.contentOffset = CGPoint(x: 0, y: feedCV.contentOffset.y - changeInHeaderViewHeight)
            }
          }
        
          // Animate the header view when the user ends dragging or flicks the scroll view 
          func scrollViewDidEndDecelerating(_ scrollView: UIScrollView) {
            animateHeaderViewHeight()
          }
        
          func scrollViewDidEndDragging(_ scrollView: UIScrollView, willDecelerate decelerate: Bool) {
            animateHeaderViewHeight()
          }
        }
        
        extension APDynamicHeaderTableViewController : UICollectionViewDataSource {
            func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
                return 100
            }
        
            func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
                let cell = collectionView.dequeueReusableCell(withReuseIdentifier: VideoCollectionViewCell.ID, for: indexPath) as! VideoCollectionViewCell
        
                return cell
            }
        
        
            func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
        
            }
        
        
        
             func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
                return largeWideSize
            }
        
        
        
        
        }
        

        【讨论】:

          【解决方案5】:

          扩展Oleg's answer...

          如果您使用 Interface Builder 为视图控制器的主视图设置约束,Xcode 默认显示选项以根据顶部布局指南设置垂直约束。但是,如果您按“选项”,您将看到一组备用约束。 'Top Space to Container' 的约束就是你要找的。​​p>

          【讨论】:

            【解决方案6】:

            我遇到了同样的问题,但使用的是网络视图。 问题是 web view 的 top 约束是 "Top Layout Guide.Top" ,将 top 约束改为 "Superview.Top" 后问题就解决了。

            【讨论】:

            • 这是我能找到的唯一可行的解​​决方案。我的案例是嵌入在 UIViewController 中的 UITableViewController。
            • 我认为答案的意思是“Top Layout Guide.Bottom”而不是“Top Layout Guide.Top”
            • 这是正确答案!但在 Xcode 7.3.1 中,这个约束很难设置。我花了一段时间才发现我必须选择超级视图和视图,然后对齐顶部边缘
            • 这个答案很清楚为什么我们迫切需要 SO
            • 这有帮助。但是如果我将 constraint.const 设置为 superview.top 它会再次停止工作。为什么这仅适用于 0 约束?
            【解决方案7】:

            我向 Apple 提交了错误报告,最终改用 AMScrollingNavbar,它运行良好且易于设置。

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 1970-01-01
              • 2021-09-05
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2022-08-03
              • 2023-04-11
              • 2023-03-14
              相关资源
              最近更新 更多