Jesper Martensson
Jesper Martensson

Reputation: 1248

Hide navigation bar when scrolling web view without navigation controller in iOS

I want the same behaviour as this

How do you hide navigation bar when scrolling in web view if the main view has a navigation bar without a navigationController? Navigation bars don't have the alternative via storyboard to check 'hide bars on swipe'.

This will not work either

self.navigationController.hidesBarsOnSwipe = true

This is what my SB looks like:

This is what my SB looks like:

Regards

Upvotes: 1

Views: 2404

Answers (2)

Shivang Pandey
Shivang Pandey

Reputation: 188

 webView.scrollView.delegate = self



extension ViewController:UIScrollViewDelegate{
    func scrollViewWillEndDragging(_ scrollView: UIScrollView, withVelocity velocity: CGPoint, targetContentOffset: UnsafeMutablePointer<CGPoint>) {
        navigationController?.hidesBarsOnSwipe  = velocity.y > 0
    }
}

Upvotes: 1

mugx
mugx

Reputation: 10105

you might try the following solution:

Swift

import UIKit

class ViewController: UIViewController, UIScrollViewDelegate {
  @IBOutlet var webView:UIWebView!
  @IBOutlet var navigationBar:UINavigationBar!
  @IBOutlet var navigationBarTop:NSLayoutConstraint!
  var lastContentOffset:CGFloat = 0.0

  override func viewDidLoad() {
    super.viewDidLoad()
    self.webView.scrollView.delegate = self
    self.webView.loadRequest(URLRequest(url: URL(string: "https://www.apple.com")!))
  }

  public func scrollViewDidScroll(_ scrollView: UIScrollView) {
    let threshold:CGFloat = 20.0
    let delta = abs(self.lastContentOffset - scrollView.contentOffset.y)
    if delta > threshold || scrollView.contentOffset.y <= 0 {
      if self.lastContentOffset > scrollView.contentOffset.y && self.navigationBarTop.constant < 0 && (self.lastContentOffset < (scrollView.contentSize.height - scrollView.frame.height)) {
        self.showNavBar(true)
      } else if (self.lastContentOffset < scrollView.contentOffset.y && self.navigationBarTop.constant == 0 && (self.lastContentOffset > 0)) {
        self.showNavBar(false)
      }
    }
    self.lastContentOffset = scrollView.contentOffset.y;
  }

  func showNavBar(_ isVisible:Bool) {
    UIView.animate(withDuration: 0.25, animations: {
      self.navigationBarTop.constant = isVisible ? 0 : -(self.navigationBar.frame.height + UIApplication.shared.statusBarFrame.height)
      self.view.setNeedsLayout()
      self.view.layoutIfNeeded()
    })
  }
}

full source code here: https://github.com/mugx/AnimatedNavigationBar

enter image description here

Objective-C

#import <UIKit/UIKit.h>

@interface ViewController : UIViewController<UIScrollViewDelegate>
@property IBOutlet UIWebView *webView;
@property IBOutlet UINavigationBar *navigationBar;
@property IBOutlet NSLayoutConstraint *navigationBarTop;
@property (nonatomic,assign) CGFloat lastContentOffset;
@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    self.webView.scrollView.delegate = self;
    [self.webView loadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:@"https://www.apple.com"]]];
}

- (void)scrollViewDidScroll:(UIScrollView *)scrollView {
    CGFloat threshold = 20.0;
    CGFloat delta = fabs(self.lastContentOffset - scrollView.contentOffset.y);
    if (delta > threshold || scrollView.contentOffset.y <= 0) {
        if (self.lastContentOffset > scrollView.contentOffset.y && self.navigationBarTop.constant < 0 && (self.lastContentOffset < (scrollView.contentSize.height - scrollView.frame.size.height))) {
            [self showNavBar:true];
        } else if (self.lastContentOffset < scrollView.contentOffset.y && self.navigationBarTop.constant == 0 && (self.lastContentOffset > 0)) {
            [self showNavBar:false];
        }
    }
    self.lastContentOffset = scrollView.contentOffset.y;
}

- (void)showNavBar:(Boolean)isVisible {
    [UIView animateWithDuration:0.25 animations:^{
        self.navigationBarTop.constant = isVisible ? 0 : -(self.navigationBar.frame.size.height + UIApplication.sharedApplication.statusBarFrame.size.height);
        [self.view setNeedsLayout];
        [self.view layoutIfNeeded];
    }];
}

@end

This is the first solution I thought, of course is not drag and drop, you have to link the respective IBOutlet. Anyway the mechanism I think is clear, leverage on scrollView delegate embedded in the webview, then calculate the delta offset in order to show/hide (with a smooth animation) your custom navigation bar. If something is not clear, I'll modify the answer.

Upvotes: 1

Related Questions