WebViewのスクロールで、toolbarやnavigationBarを隠す


# やること

WebViewをスクロールして下げていくとtoolbarを隠し
上げると表示させる機能を実装したいと思います。

## はじめに

NavigationControlerをトップにつけます。

デフォルトで、表示されているViewControllerを選択し

Xcodeのメニューから

```Editor　→　Embed In　→　Navigation Contoroller```　で追加できます。

![1.png](https://qiita-image-store.s3.amazonaws.com/0/60014/5de55b31-d987-81cf-e45e-0d199d6565cc.png "1.png")


追加後に、```Shows　Toolbar```にチェックを入れます。

![2.png](https://qiita-image-store.s3.amazonaws.com/0/60014/e840cfa8-a6fe-7379-624a-2e3366b15a7b.png "2.png")


これで、デフォルトのViewControllerにtoolbarが追加されました。
 
## WebViewのスクロールイベントを取得する


WebViewには、iOS5からscrollViewが子クラスとして設定されているので、そいつのデリゲートを取得する

 
```ViewController.swift

import UIKit

class ViewController: UIViewController, UIWebViewDelegate, UIScrollViewDelegate {

	@IBOutlet weak var webView: UIWebView!

	var beginingPoint: CGPoint!
    var isViewShowed: Bool!
	
	override func viewDidLoad() {
		super.viewDidLoad()
		// 各種初期化
        isViewShowed = false
		beginingPoint = CGPoint(x: 0, y: 0)
		webView.delegate = self
		webView.scrollView.delegate = self
		
		// とりあえず、Google表示してみる
		let url: NSURL = NSURL(string:"https://www.google.co.jp/")
		webView.loadRequest(NSURLRequest(URL:url))
	}

    override func viewDidAppear(animated: Bool) {
        isViewShowed = true
    }
	
	// WebViewをスクロールする際に開始時の値をセット
	func scrollViewWillBeginDragging(scrollView: UIScrollView) {
		beginingPoint = scrollView.contentOffset
	}
	
	// WebViewのスクロールイベント取得　開始時の値と比較してToolbarを表示・非表示
	func scrollViewDidScroll(scrollView: UIScrollView) {
		var currentPoint = scrollView.contentOffset
		var contentSize = scrollView.contentSize
		var frameSize = scrollView.frame
		var maxOffSet = contentSize.height - frameSize.height
		
		if isViewShowed == true && currentPoint.y < maxOffSet {
			self.navigationController?.setToolbarHidden(true, animated: true)
		} else {
			self.navigationController?.setToolbarHidden(false, animated: true)
		}
	}
}
```

これで、上にスクロールしている時は非表示。下にスクロールしている時は表示になると思います。

contentOffsetと比較を行うことで、最後までスクロールした際にbounceを付けていた場合、toolbarがガタガタと動作がおかしくなります。bounceを切ってもいいんですが、UIRefreshControlを使って更新（下に引っ張って更新）を行いたいのでこのような形になりました。

##追記

@sassymanyuichiさんから頂いたコメントのように

```
func scrollViewDidScroll(scrollView: UIScrollView) {
    let currentPoint = scrollView.contentOffset
    let contentSize = scrollView.contentSize
    let frameSize = scrollView.frame
    let maxOffSet = contentSize.height - frameSize.height

    if currentPoint.y >= maxOffSet {
        print("hit the bottom")
        self.navigationController?.setToolbarHidden(true, animated: true)
    } else if scrollBeginingPoint.y < currentPoint.y {
        //print("Scrolled down")
        self.navigationController?.setToolbarHidden(true, animated: true)
    }else{
        //print("Scrolled up")
        self.navigationController?.setToolbarHidden(false, animated: true)
    }
}
```

のように実装すると、スムーズにスクロールできます。

### NavigationBarを隠す場合

```
func scrollViewDidScroll(scrollView: UIScrollView) {
        let currentPoint = scrollView.contentOffset
        let contentSize = scrollView.contentSize
        let frameSize = scrollView.frame
        let maxOffSet = contentSize.height - frameSize.height
        
        if currentPoint.y >= maxOffSet {
            print("hit the bottom")
            navigationController?.hidesBarsOnSwipe = true
        } else if beginingPoint.y < currentPoint.y {
            //print("Scrolled down")
            navigationController?.hidesBarsOnSwipe = true
        }else{
            //print("Scrolled up")
            // NavigationBarを表示
            navigationController?.navigationBarHidden = false
            navigationController?.hidesBarsOnSwipe = false
        }
}
```

このような感じでいけます。