スライドショーはショーケースモード(左右に前後の画像が少し見えるヤツ)でも対応したい。一旦1枚表示モードに切り替えてからスライドショー実行し、終了時に元にもどるようなイメージ。
その為には両モードの切り替えが自由にできるようにならないといけない。今回はその切替。
リファクタリング
ビュー階層はこんな感じになっている。
これらのビューの位置やサイズは初期処理内だけで行っていた。
-(void)初期処理 { 表示モードによる初期処理 ベースのUIScrollViewの位置・サイズ設定処理 画像を表示する XCGalleryInnerScrollView の生成と位置・サイズ設定処理 }
各ビューの位置とサイズ設定処理は、モード変更時にも発生するのでこれらをメソッドとして切り出す。
-(void)表示モード設定 { : } -(void)ベース UIScrollView位置・サイズ設定 { : } XCGalleryInnerScrollView位置・サイズ設定{ : } -(void)初期処理() { [self 表示モード設定]; : [self ベースUIScrollView位置・サイズ設定]; : [self XCGalleryInnerScrollView位置・サイズ設定]; : }
一旦切り出せば再利用可能になるので、これをモード切替時に呼び出す。実際にはスクリーンのローテーション時にもレイアウト変更が発生するので使える。
(コードは割愛)
サンプル実行
静止画だとわかりずらいが、左下のボタンで両方のモードを行き来できる。
通常モード
ショーケースモード
なお切替時のレイアウト変更処理を +[UIView beginAnimations:context:] と +[UIView commitAnimations]で囲うことでアニメーションするようにしてある。
- (void)setShowcaseModeEnabled:(BOOL)enabled animated:(BOOL)animated { showcaseModeEnabled_ = enabled; passDidScroll_ = YES; [UIView beginAnimations:nil context:nil]; [self setupSpacingAndMargin]; [self relayoutBaseScrollView]; [self relayoutInnerScrollViews]; [UIView commitAnimations]; }
scrollViewDidScroll:
UIScrollView の contentSize や contentOffset を変更した場合も UIScrollViewDelegate の -scrollViewDidScroll: が呼ばれる。前回まではこのメソッドは指でスクロールさせた時の処理が書いてあり、これらプロパティの変更に伴うスクロールは考慮していなかった。この為、モードを切り替えた時の contentSize/contentOffset 変更によっても -scrollViewDidScroll: が呼び出され意図しない動作が発生していた。例えば6ページ目を見ている状態でモードを切り替えると表示が7ページ目に移動してしまう。これはモードの切り替えにより contentSize/contentOffsetが再設定され、その結果 -scrollViewDidScroll:が呼ばれ、さらに一定のスクロール量が発生したとみなされるとこのメソッド内で次ページもしくは前ページへの移動処理が走ってしまうため。
プロパティ変更と指によるスクロールの判別の方法がわからなかったので、今回はメンバ変数 BOOL passDidScroll_ を用意し、プロパティ変更を行う場合はあらかじめ YES を設定するようにした。
: passDidScroll_ = YES; self.scrollView.contentSize = CGSizeMake( [self.delegate numberImagesInGallery:self]*newSizeWithSpace.width, newSize.height); passDidScroll_ = YES; self.scrollView.contentOffset = CGPointMake( self.contentOffsetIndex*newSizeWithSpace.width, 0); :その上で、-scrollViewDidScroll: 内ではこのフラグが立っている場合は1回処理をスキップする処理を加えた。
- (void)scrollViewDidScroll:(UIScrollView *)scrollView { if (passDidScroll_) { passDidScroll_ = NO; return; } :ベタなやり方だがとりあえず問題は回避できた。
ソースコード
GitHubからどうぞ。
EasyGallery at 2010-10-20 from xcatsan's iOS-Sample-Code - GitHub
Responses
Leave a Response