スライドショーはショーケースモード(左右に前後の画像が少し見えるヤツ)でも対応したい。一旦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