滚动时,hidesBarsOnSwipe从不再显示导航栏

时间:2014-10-31 13:16:05

标签: objective-c swift ios8

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

完美配合
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)
}
}

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

7 个答案:

答案 0 :(得分:43)

我遇到了同样的问题但是有了网络视图。 问题是Web视图的顶部约束是“Top Layout Guide.Top”,在将顶部约束更改为“Superview.Top”后问题得以解决。

答案 1 :(得分:10)

展开Oleg's answer ...

如果使用Interface Builder将约束设置为视图控制器的主视图,则Xcode默认显示用于针对顶部布局指南设置垂直约束的选项。但是,如果按“选项”,您将看到一组备用约束。 “顶级空间到容器”的约束是您正在寻找的。

答案 2 :(得分:2)

我向Apple提交了一份错误报告,最后使用了AMScrollingNavbar,但效果非常好并且易​​于设置。

答案 3 :(得分:2)

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

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

答案 4 :(得分:2)

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

class ViewController: UIViewController {

   override func viewDidLoad() {
      super.viewDidLoad()
      self.navigationController?.hidesBarsOnSwipe = true
   }
}

hidesBarsOnSwipe 设置为true只会在我们将UITableViewController或UICollectionViewController用作主屏幕时有效,而 hidesBarsOnSwipe 如果我们向UIViewController添加了UITableView,则将不起作用用于显示数据列表。

解决方案

class TestTableViewController: UITableViewController {

    override func viewDidLoad() {
       super.viewDidLoad()
       self.navigationController?.hidesBarsOnSwipe = true
    }
}

希望这个答案可能对您有帮助...!

答案 5 :(得分:0)

根据之前的评论 - 这似乎是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
    }




}

答案 6 :(得分:0)

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