[iOS] スクロール中に気持ち良くナビゲーションバーを隠してくれるライブラリ、NJKScrollFullScreenについて
1 はじめに
NJKScrollFullScreenは、スクロール操作に応じてナビゲーションバーなどを表示/非表示することが簡単にできるライブラリです。 スクロールのイベントをフックしてバーの高さを変えるという処理は、元々自前でも記述可能ですが、このライブラリを使用することで、より簡単に気持ちく動作するUIが作成できます。
NJKScrollFullSreenはUIScrollView、UIWebView及び、UITableViewに対応しています。
NJKScrollFullScreenは、MITライセンスで公開されており、CocoaPodで簡単にインストールが可能です。
pod 'NJKScrollFullScreen'
なお、2016年3月現在、最新は、0.2.6です。
ライブラリの導入後は、下記のインポートで利用可能になります。
#import "NJKScrollFullScreen.h" #import "UIViewController+NJKFullScreenSupport.h"
2 使用方法
(1) ナビゲーションバー/ツールバーの表示・非表示
Cocoapodsで導入後、新しいプロジェクトをSingle View Applicationで作成し、メニューからEditor-Enbed In-Navigation Controllerを選択して、NavigationControllerで始まるようにします。
また、NavigationControllerの設定で、show toolbarにチェックを入れて、上下にバーが表示されるように します。
この状態で、動作確認すると、下図のように上にナビゲーションバーが表示された画面となります。
ちょっと分かりやすいようにナビゲーションバーとツールバーの色を変更しましたが、これは、NavigationControllerの方のNavigation BarとToolbarのBar Tintで変更しています。
続いて、実験的に2つのボタンを置いて、次のようなコードを書いてみます。
動作確認している様子です。
showNavigationBar:やhideNavigationBar:のようなコードで、簡単にバーの表示/非表示ができます。
UIViewController+NJKFullScreenSupport.hの中を確認すると、次のようなメソッドがUIViewControllerに追加されていることが分かります。
#import <UIKit/UIKit.h> @interface UIViewController (NJKFullScreenSupport) - (void)showNavigationBar:(BOOL)animated; - (void)hideNavigationBar:(BOOL)animated; - (void)moveNavigationBar:(CGFloat)deltaY animated:(BOOL)animated; - (void)setNavigationBarOriginY:(CGFloat)y animated:(BOOL)animated; - (void)showToolbar:(BOOL)animated; - (void)hideToolbar:(BOOL)animated; - (void)moveToolbar:(CGFloat)deltaY animated:(BOOL)animated; - (void)setToolbarOriginY:(CGFloat)y animated:(BOOL)animated; - (void)showTabBar:(BOOL)animated; - (void)hideTabBar:(BOOL)animated; - (void)moveTabBar:(CGFloat)deltaY animated:(BOOL)animated; - (void)setTabBarOriginY:(CGFloat)y animated:(BOOL)animated; @end // Compatible method for typo fixed (https://github.com/ninjinkun/NJKScrollFullScreen/pull/23) @interface UIViewController (NJKFullScreenSupportDeprecated) - (void)moveNavigtionBar:(CGFloat)deltaY animated:(BOOL)animated __deprecated_msg("Use `moveNavigationBar:animated:`"); @end
今は、Show/Hideで表示・非表示だけを試しましたが、サイズを細かく指定するメソッドもあり、これらを適切なタイミングで呼び出すことで、スクロールに合わせてバーのサイズを変化させることができます。
なお、実装としては、UIViewController+NJKFullScreenSupport.mを見ると、画面サイズを考慮しながら、バーを指定されたサイズに変更するような実装になっていました。
(2) (プロキシー)デリゲート
実験的に置いた、先ほどのボタンは削除し、今度は、画面いっぱいにUIWebViewを置いてみます。
そして、起動時に、Webページを表示するコードを追加します。
※iOS9以降については、ATSを適切に設定してください。
参考:[iOS 9] iOS 9 で追加された App Transport Security の概要
- (void)viewDidLoad { [super viewDidLoad]; NSURL *url = [NSURL URLWithString:@"https://dev.classmethod.jp/"]; NSURLRequest *req = [NSURLRequest requestWithURL:url]; [_webView loadRequest:req]; }
動作は、次のとおりです。当然ですが、UIWebViewを操作しても、上下のバーに変化はありません。
ここで、UIWebViewをスクロールした時に、気持ちよく上下のナビゲーションバーやツールバーが消えると画面が広くなって見やすいのですが、そのためには、UIWebViewのスクロールイベントをフックする必要があります。
NJKScrollFullScreenでは、スクロールにあわせて、気持ちよくバーのサイズを変更できるように、必要なスクロール(移動数)を追加してデリゲートとして提供しています。
そして、このために、まずはNJKScrollFullScreenを、対象コントロール(今は、UIWebView)のデリゲートに登録し、さらに、自分自身(今は、ViewController)をNJKScrollFullScreenのデリゲートに登録するという設定が必要です。
普通であれば、UIWebViewのデリゲートに自分自分(ViewController)を設定して処理するスクロールのイベントを、NJKScrollFullScreen経由で受け取るイメージです。
実装としては、次のようになります。 なお、NJKScrollFullScreen.hのインポートと、NJKScrollFullscreenDelegateと追加することも必要です。
#import "NJKScrollFullScreen.h" #import "UIViewController+NJKFullScreenSupport.h" @interface ViewController ()<NJKScrollFullscreenDelegate> @property (weak, nonatomic) IBOutlet UIWebView *webView; @property (nonatomic) NJKScrollFullScreen *scrollProxy; @end @implementation ViewController - (void)viewDidLoad { [super viewDidLoad]; // 省略 // NJKScrollFullScreenの生成 self.scrollProxy = [[NJKScrollFullScreen alloc] initWithForwardTarget:self]; // UIWebViewのスクロールビューのデリゲートにNJKScrollFullScreenをセットする self.webView.scrollView.delegate = (id)self.scrollProxy; // NJKScrollFullScreenのデリゲートに自信をセットする self.scrollProxy.delegate = self; }
(3) スクロール時の処理
続いて、NJKScrollFullScreenによって提供されるデリゲートメソッドでナビゲーションバー及びツールバーの表示非表示を行います。
- (void)scrollFullScreen:(NJKScrollFullScreen *)proxy scrollViewDidScrollUp:(CGFloat)deltaY { [self moveNavigationBar:deltaY animated:YES]; [self moveToolbar:-deltaY animated:YES]; } - (void)scrollFullScreen:(NJKScrollFullScreen *)proxy scrollViewDidScrollDown:(CGFloat)deltaY { [self moveNavigationBar:deltaY animated:YES]; [self moveToolbar:-deltaY animated:YES]; } - (void)scrollFullScreenScrollViewDidEndDraggingScrollUp:(NJKScrollFullScreen *)proxy { [self hideNavigationBar:YES]; [self hideToolbar:YES]; } - (void)scrollFullScreenScrollViewDidEndDraggingScrollDown:(NJKScrollFullScreen *)proxy { [self showNavigationBar:YES]; [self showToolbar:YES]; }
実行している様子は、次の通りです。
3 最後に
簡単なコストで気持ちの良いインターフェースが実装できるNJKScrollFullScreenは、すごいと思います。 今回は、UIWebViewを例にしましたが、最初に書いたとおり、ここは、UIScrollViewやUITableViewに置き換えても同じように使用できます。
なお、下記は、作者のSatoshi Asano氏のGitHub活動について紹介されているスライドです。非常に興味深く読ませて頂きました。
GitHub活動を通して個人のキャリアを積みつつ仕事の成果を出す方法
4 参考資料
COCOAPODS NJKScrollFullScreen
https://github.com/ninjinkun/NJKScrollFullScreen