2024.11.14
いまさらNode.jsを知ろう~環境構築も~
2014.06.19
プログラミング自作のツールバーがiOSのSafariっぽく動くようにする
こんにちは、ZYです。
今回は、
「その動き、君がいいねと言ったら、Safari記念日」
ということで、「なんかiOSのSafariっぽい挙動をする自作ツールバー」を紹介します。
と、いっても、今回再現するのは、「スクロール時やタップ時に、ツールバーが出たり引っ込んだりする動き」です。中のボタンの動きなんかは再現しないので、あしからず。
さて。まずは、iOSのSafariで使われているToolBarの挙動を確認しておきましょう。
出てくるイベント
1.勢いよく上にスクロール(指は下にpan)した時
(ゆっくりした時は、出てこない)
2.一番下までスクロールした時
3.画面下部をタップした時
隠れるイベント
4.下にスクロールした時
(スクロールにあわせて、途中までゆっくり降りて、ある程度まで行くとアニメーションで隠れる)
以上の動作を、各イベントにあわせて自作のツールバーが動くように実装していきます。
以下が、そのコードです。
@interface ImitateSafariToolBarViewController : UIViewController<UIScrollViewDelegate> // スクロールビュー @property UIScrollView *scrollView; // 自作ツールバー 縦幅44 @property UIView *toolBar; // 制御用の変数たち。 @property BOOL showReplyView; @property BOOL animetionReplyView; @end
// 自作ツールバーを動かすイベントを取るUIScrollViewデリゲート群。 // スクロールが始まった時に呼ばれるメソッド - (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView { // 今回は特に何もなし。 } // スクロール中に呼ばれる -(void)scrollViewDidScroll:(UIScrollView *)scrollView { // velocityInViewは、panの「速さ」を取得します CGPoint v = [scrollView.panGestureRecognizer velocityInView:scrollView]; if(v.y > 800){ // 勢いよく上にスクロールした場合。800は、割と反応しやすい方。 // SafariのToolBarに近づけるなら、1100以上でもいいかも? [self showToolBar]; } // translationInViewは、pan開始時から現在地までの「距離」を取得 CGPoint p = [scrollView.panGestureRecognizer translationInView:scrollView]; if(p.y <= -1){ if (_animetionReplyView) return; if (! _showReplyView) return; // 上にスクロールした場合 // パンの動きに連動して、閉じる方向に少しずつ動く CGRect frame = self.toolBar.frame; frame.origin.y = self.view.frame.size.height - self.toolBar.frame.size.height + (p.y * -1); self.toolBar.frame = frame; // 一定の位置まで行くと閉じる。 if (p.y < -22) { [self hideToolBar]; } } } // ドラッグが終了した時に呼ばれる - (void)scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL)decelerate { // 一番下まで行くと、ツールバーを出す。 if (scrollView.contentOffset.y > scrollView.contentSize.height - scrollView.frame.size.height) { [self showToolBar]; } // ツールバーがゆっくり下がっている途中で離した際には、ちょっとずれてるので、戻す if (_showReplyView && !_animetionReplyView) { if (self.toolBar.frame.origin.y != self.view.frame.size.height - self.toolBar.frame.size.height) { _showReplyView = NO; [self showToolBar]; } } } // 慣性で動くスクロールが静止したときに呼ばれる。基本的にはドラッグを離した時と同じような動作。 - (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView { // 一番下ならツールバーを出す if (scrollView.contentOffset.y > scrollView.contentSize.height - scrollView.frame.size.height) { _showReplyView = NO; [self showToolBar]; } if (_showReplyView && !_animetionReplyView) { if (self.toolBar.frame.origin.y != self.view.frame.size.height - self.toolBar.frame.size.height) { [self showToolBar]; } } } // 自作ツールバーの閉じたり出たりのアニメーション。 -(void)showToolBar{ // ツールバーを出す // アニメーションの途中や、もうすでに開いてる時は動作しない。 //if (_animetionReplyView) return; if (_showReplyView) return; _animetionReplyView = YES; CGRect frame = self.toolBar.frame; frame.origin.y = self.view.frame.size.height - self.toolBar.frame.size.height; [UIView animateWithDuration:0.2f delay:0.0f options:UIViewAnimationOptionCurveLinear animations:^{ self.toolBar.frame = frame; } completion:^(BOOL finished){ _animetionReplyView = NO; _showReplyView = YES; }]; } -(void)hideToolBar{ // ツールバーを隠す NSLog(@"end"); //if (_animetionReplyView) return; if (!_showReplyView) return; _animetionReplyView = YES; [UIView animateWithDuration:0.2f delay:0.0f options:UIViewAnimationOptionCurveLinear animations:^{ CGRect frame = self.toolBar.frame; frame.origin.y = self.view.frame.size.height; self.toolBar.frame = frame; } completion:^(BOOL finished){ _animetionReplyView = NO; _showReplyView = NO; }]; }
UIScrollViewのデリゲートメソッドを使っているので、UIScrollViewもしくは、その継承Class(UITableViewとか、UITextViewとか)が存在しているUIViewControllerでお使いください。
UITableViewでも、<UITableViewDelegate>を指定してやれば、ついでにUIScrollViewDelegateが呼び出されます。
今回は自作のツールバーを使いましたが、UINavigationControllerのtoolBarを使うことも可能。
上記のself.toolBarを、self.navigationController.toolbarに変えれば、基本的にはOK。
ふつーにself.navigationController.toolbar.frameをいじれば、動きます。
一応、
-(void)showToolBar;
-(void)hideToolBar;
を呼び出しているところを
[self.navigationController setToolbarHidden:YES animated:YES];
[self.navigationController setToolbarHidden:NO animated:YES];
に変えても動きますが・・・私がやった時は、たまにエラー落ちしてたので、あんまりおすすめしないです。
ま、でも、たぶん、ある程度条件つけて、呼び出すタイミングを制御してやれば、大丈夫ですよ、たぶん。
その他、一番下までスクロールしなくても出るようにするなど、カスタムしてお使いください。
【記事への感想募集中!】
記事への感想・ご意見がありましたら、ぜひフォームからご投稿ください!【テクノデジタルではエンジニア/デザイナーを積極採用中です!】
下記項目に1つでも当てはまる方は是非、詳細ページへ!Qangaroo(カンガルー)
【テクノデジタルのインフラサービス】
当社では、多数のサービスの開発実績を活かし、
アプリケーションのパフォーマンスを最大限に引き出すインフラ設計・構築を行います。
AWSなどへのクラウド移行、既存インフラの監視・運用保守も承りますので、ぜひご相談ください。
詳細は下記ページをご覧ください。
最近の記事
タグ検索