[iOS] スクロール中に気持ち良くナビゲーションバーを隠してくれるライブラリ、NJKScrollFullScreenについて

2016.03.07

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

1 はじめに

NJKScrollFullScreenは、スクロール操作に応じてナビゲーションバーなどを表示/非表示することが簡単にできるライブラリです。 スクロールのイベントをフックしてバーの高さを変えるという処理は、元々自前でも記述可能ですが、このライブラリを使用することで、より簡単に気持ちく動作するUIが作成できます。

NJKScrollFullSreenUIScrollViewUIWebView及び、UITableViewに対応しています。

NJKScrollFullScreenは、MITライセンスで公開されており、CocoaPodで簡単にインストールが可能です。

pod 'NJKScrollFullScreen'

参考:CocoaPodsによる、外部ライブラリの利用と作成

なお、2016年3月現在、最新は、0.2.6です。

ライブラリの導入後は、下記のインポートで利用可能になります。

#import "NJKScrollFullScreen.h"
#import "UIViewController+NJKFullScreenSupport.h"

2 使用方法

(1) ナビゲーションバー/ツールバーの表示・非表示

Cocoapodsで導入後、新しいプロジェクトをSingle View Applicationで作成し、メニューからEditor-Enbed In-Navigation Controllerを選択して、NavigationControllerで始まるようにします。

001

また、NavigationControllerの設定で、show toolbarにチェックを入れて、上下にバーが表示されるように します。

003

この状態で、動作確認すると、下図のように上にナビゲーションバーが表示された画面となります。

002

ちょっと分かりやすいようにナビゲーションバーとツールバーの色を変更しましたが、これは、NavigationControllerの方のNavigation BarToolbarBar Tintで変更しています。

008

009

続いて、実験的に2つのボタンを置いて、次のようなコードを書いてみます。

005

動作確認している様子です。

004

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を置いてみます。

007

そして、起動時に、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を操作しても、上下のバーに変化はありません。

006

ここで、UIWebViewをスクロールした時に、気持ちよく上下のナビゲーションバーやツールバーが消えると画面が広くなって見やすいのですが、そのためには、UIWebViewのスクロールイベントをフックする必要があります。

NJKScrollFullScreenでは、スクロールにあわせて、気持ちよくバーのサイズを変更できるように、必要なスクロール(移動数)を追加してデリゲートとして提供しています。

そして、このために、まずはNJKScrollFullScreenを、対象コントロール(今は、UIWebView)のデリゲートに登録し、さらに、自分自身(今は、ViewController)をNJKScrollFullScreenのデリゲートに登録するという設定が必要です。

010

普通であれば、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];
}

実行している様子は、次の通りです。

011

3 最後に

簡単なコストで気持ちの良いインターフェースが実装できるNJKScrollFullScreenは、すごいと思います。 今回は、UIWebViewを例にしましたが、最初に書いたとおり、ここは、UIScrollViewUITableViewに置き換えても同じように使用できます。

なお、下記は、作者のSatoshi Asano氏のGitHub活動について紹介されているスライドです。非常に興味深く読ませて頂きました。
GitHub活動を通して個人のキャリアを積みつつ仕事の成果を出す方法

4 参考資料


COCOAPODS NJKScrollFullScreen
https://github.com/ninjinkun/NJKScrollFullScreen