簡易スライドビューア [17] モードの切り替え

2010年10月20日水曜日 | Published in | 0 コメント

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

[前回] Cocoaの日々: 簡易スライドビューア [16] スライドショー(3) 停止その2

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

人気の投稿(過去 30日間)