2012/11/26更新

[XCODE] Pull To Refreshを実現する実装方法

このエントリーをはてなブックマークに追加      

こんにちは、iPhoneアプリ開発を再開した@yoheiMuneです。
今日は、Twitterクライアントとかで良くあるPull To Refreshを実装する方法をブログに記載したいと思います。

画像



プルリフレッシュ(Pull to Refresh)とは

プルリフレッシュとは、TwitterクライアントやFacebookアプリなどで採用されているUIで、 TableViewのトップで、下にドラッグする事で、TableViewの内容を更新するUIです。

例えば、以下のような画面が良く採用されています。
画像


プルリフレッシュを簡単に実現する場合は、Githubで公開されているPullToRefreshを取り入れることで実現出来ます。
しかし今回のブログでは、PullToRefreshの内容と同じ実装方法を、スクラッチで作る方法を紹介したいと思います。
上記のGithubのコードを読むと、「こんなに簡単にできるのかー」と驚いたので、その実装方法を紹介したいという意味でブログを書きました。



プルリフレッシュを実装する方法

今回は、UITableViewを用いたアプリケーションで、プルリフレッシュを実現する方法です。

作り方は簡単で、以下の事を行うとプルリフレッシュを実現出来ます。
  • PullToRefresh用のラベルをUITableView上にaddSubViewする
  • UIScrollViewDelegateを用いて、ドラッグ開始と終了のイベントを捉える
  • UIScrollViewDelegateを用いて、スクロール位置を監視し、スロール量により処理を行う
  • ドラッグが終了した際に、スクロール量に合わせてリフレッシュ処理を行う
以下ではそれぞれの実装内容を紹介します。


PullToRefresy用のラベルをUITableView上にaddSubViewする

まずは、PullToRefresh用のラベルを作成して、UITableView上に配備します。
UIViewControllerの実装などで、以下のようなコードを記載します。
// プルリフレッシュ用ラベルの高さ
#define REFRESH_VIEW_HEIGHT 100
- (void)viewDidLoad {
    [super viewDidLoad];
        
    // プルリフレッシュ用のViewを作成する。
    // ポイントは、Rectのy座標を負数にしておくこと。
    // そうすることで、上にドラッグした時のみに見えるようになる。
    refreshView = [[UIView alloc] initWithFrame:CGRectMake(0, 0 - REFRESH_VIEW_HEIGHT, self.view.frame.size.width, REFRESH_VIEW_HEIGHT)];
    // プルリフレッシュ用のViewを、tableViewのサブViewとして追加する。
    refreshView.backgroundColor = [UIColor purpleColor];
    [tableView addSubview:refreshView];
}
今回は、紫色のViewを追加しましたが、アプリ毎に追加で必要な情報があれば、refreshViewに追加することも可能です。



UIScrollViewDelegateを用いて、ドラッグ開始と終了のイベントを捉える

続いて、UITableViewが継承しているUIScrollView用のDelegateを使い、ドラッグ開始/終了を捉えます。
- (void)viewDidLoad {
    [superviewDidLoad];

    // tableViewのdelegateは、UITableViewDelegateですが、
    // UITableViewDelegateは、UIScrollViewDelegateを継承(実装)しているため、
    // tableViewのdelegateに、UIScrollViewDeleageteを実装したselfを追加する事が可能です。
    tableView.delegate = self;    
}

// 以下ではUIScrollViewDelegateを実装していて、ドラッグ中か否かを、グローバル変数に保存します。
#pragma mark - UIScrollViewDelegate
- (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView {
    isDragging = YES;
    return;
}

- (void)scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL)decelerate {
    isDragging = NO;
    return;
}
ドラッグ中か否かの情報が必要な理由として、ユーザーがドラッグしてUITableViewの上に設置したRefreshViewを表示しているのか、 ただ勢い良くスクロースしたから惰性で表示されたのかを判断する必要があるからです。
ユーザーがわざわざドラッグして表示してる場合には、Refreshが意図した通りに動くように、実装します。



UIScrollViewDelegateを用いて、スクロール位置を監視し、スロール量により処理を行う

スクロールを監視して、スクロール量により処理を行います。
#pragma mark - UIScrollViewDelegate
- (void)scrollViewDidScroll:(UIScrollView *)scrollView {

    // ドラッグ中以外は、必要ないので処理しない。
    if (!isDragging) return;
    
    // 今回は、スクロール量により、RefreshViewの背景色を変更しています。
    // 他にも、表示するテキストを変更するなど、UX向上のためのUI更新を行う。
    float y = scrollView.contentOffset.y;
    if (y < 0) {
        if (y > (-REFRESH_VIEW_HEIGHT)) {
            if (refreshView.backgroundColor != [UIColor purpleColor]) {

                refreshView.backgroundColor = [UIColor purpleColor];
            }
        } else {
            if (refreshView.backgroundColor != [UIColor redColor]) {

                refreshView.backgroundColor = [UIColor redColor];
            }
        }
    }
}

スクロール量により、どんな処理が行われるのか/行われないのかを、ユーザーへ示す必要があります。
ここでの処理は、RefreshViewの内容を変更することで、何を行うのかを示します。



ドラッグが終了した際に、スクロール量に合わせてリフレッシュ処理を行う

最後に、本命のリフレッシュ処理を行います。
ドラッグが終了した時点でのスクロール量に応じて、リフレッシュ処理を行います。
- (void)scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL)decelerate {
    isDragging = NO;

    float y = scrollView.contentOffset.y;
    
    // スクロール量に合わせて、処理を行う。
    if (y < (-REFRESH_VIEW_HEIGHT)) {
        [self refresh];
    }
    return;
}

今回は、RefreshViewが全て見えている状態でドラッグが終了した場合に、リフレッシュ処理を行うように実装しています。



最後に

ドラッグやスワイプでコントロールアプリケーションってなんだか良いなぁと感じる今日この頃です。
タップは、画面への触れ方によっては反応しないことがありますが、スワイプやドラッグなどの大きな動作は、比較的に操作ミスが少なくていいと感じています。

次のiPhoneアプリはデザイン/操作性/機能性ともに良いものを出したいと思います。

最後までご覧頂きまして、ありがとうございました。





こんな記事もいかがですか?

RSS画像

もしご興味をお持ち頂けましたら、ぜひRSSへの登録をお願い致します。