iPhoneホームのようなページングが、かなりお手軽に作成できるのでちょっとびっくり。
基本的にはUIScrollViewだけで完結しますが、UIPageControlで現在のページ状況を表示できます。 ちなみにUIPageControlはUIViewの子です。
ポイントはUIScrollViewのframeのサイズを利用して横スクロールさせる、つまり映画のフレーム方式です。 Flash制作者の人ならよく使う技ですけど、ごり押しコードでなくもっとシステマティックですw
表示するページコンテンツをいつ追加するかはアプリによると思いますが、 とりあえず全ページ作られた状態でスクロールする方法で。
まず、定義から。
@interface HomeViewController : UIViewController {
UIScrollView *scrollView;
UIView *pageView;
UIPageControl *pageControl;
}
@property (nonatomic, retain) IBOutlet UIScrollView *scrollView;
@property (nonatomic, retain) IBOutlet UIView *pageView;
@property (nonatomic, retain) IBOutlet UIPageControl *pageControl;
@end
UIViewControllerのViewにscrollViewとpageControlを追加します。 さらにscrollViewでページングで表示するViewをpageViewとしました。 あとはスクロールの機能を使うので、UIScrollViewDelegateの追加を。
(1)scrollViewでページングで表示するView(pageView)を追加する ※PageViewは、IBOutlet *pageViewにバインド
このViewに1ページずつコンテンツを作ります。 サイズは320px/1ページになるかと思います。
(2) ViewにUIScrollViewとUIPageControlを配置する ※ScrollViewは、IBOutlet *scrollViewにバインド ※PageControlは、IBOutlet *pageControlにバインド
(3) UIScrollViewのdelegateをFile's Ownerにバインドする
delegateしておくことで自動的にscrollViewDidScrollが呼ばれます。 ちなみに、UIScrollViewのDelegateメソッドを調べると、
- (void)scrollViewDidScroll:(UIScrollView *)scrollView; // any offset changes
- (void)scrollViewDidZoom:(UIScrollView *)scrollView __OSX_AVAILABLE_STARTING(__MAC_NA,__IPHONE_3_2); // any zoom scale changes
- (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView; // called on start of dragging (may require some time and or distance to move)
- (void)scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL)decelerate; // called on finger up if user dragged. decelerate is true if it will continue moving afterwards
- (void)scrollViewWillBeginDecelerating:(UIScrollView *)scrollView; // called on finger up as we are moving
- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView; // called when scroll view grinds to a halt
- (void)scrollViewDidEndScrollingAnimation:(UIScrollView *)scrollView; // called when setContentOffset/scrollRectVisible:animated: finishes. not called if not animating
- (UIView *)viewForZoomingInScrollView:(UIScrollView *)scrollView; // return a view that will be scaled. if delegate returns nil, nothing happens
- (void)scrollViewWillBeginZooming:(UIScrollView *)scrollView withView:(UIView *)view __OSX_AVAILABLE_STARTING(__MAC_NA,__IPHONE_3_2); // called before the scroll view begins zooming its content
- (void)scrollViewDidEndZooming:(UIScrollView *)scrollView withView:(UIView *)view atScale:(float)scale; // scale between minimum and maximum. called after any 'bounce' animations
- (BOOL)scrollViewShouldScrollToTop:(UIScrollView *)scrollView; // return a yes if you want to scroll to the top. if not defined, assumes YES
- (void)scrollViewDidScrollToTop:(UIScrollView *)scrollView; // called when scrolling animation finished. may be called immediately if already at top
これで、ズームもいけちゃうっぽい!?
次に実装です。
#import "HomeViewController.h"
@implementation HomeViewController
@synthesize scrollView;
@synthesize pageView;
@synthesize pageControl;
- (void)viewDidLoad {
[super viewDidLoad];
scrollView.pagingEnabled = YES;
scrollView.contentSize = CGSizeMake(640, 0);
scrollView.showsHorizontalScrollIndicator = NO;
scrollView.showsVerticalScrollIndicator = NO;
scrollView.scrollsToTop = YES;
pageControl.numberOfPages = 2;
pageControl.currentPage = 0;
[scrollView addSubview:pageView];
}
- (void)scrollViewDidScroll:(UIScrollView *)sender {
CGFloat pageWidth = scrollView.frame.size.width;
pageControl.currentPage = floor((scrollView.contentOffset.x - pageWidth / 2) / pageWidth) + 1;
}
@end
実は
scrollViewのcontentSizeの設定と、pagingEnabledを有効する
だけでページングできてしまうのです。素晴らしい! 始めはこれを知らずに、scrollViewの位置とかで計算しようとしてましたw
UIScrollView scrollViewDidScrollを利用して、pageControlに現在のページ情報を設定します。 scrollViewの幅を計算して出してるところが力技っぽいけど。 将来的には、ページング周りのAPIが充実してくれるとうれしいですね。 (実はもうあったり!?)