ちなみに
とすることで、ドラッグで範囲外までスクロールしてから戻るという動作(スクロールバウンスアニメーション)を禁止できます。こいつはデフォルトはYESです。
同じように
で、ピンチで許可したズーム範囲外までズームを許してから範囲内に戻る(ズームバウンスアニメーション)という動作をゆるします。こっちは逆にデフォルトがNOみたいっす。
ズーム範囲を0.5~2.0(元々の0.1~10.0はいっぱいピンチしないと範囲外にいかないからね)あたりにして試してみてちょ。
で、触ってて気づいたのが、ズームアウト、こんな感じのところで手を離すとスクロールができなくなるんですわ、前回のサンプル。
右がはみ出てるのにスクロールできない。
なにこれ?
バグじゃんと思ったら、そのとおりでサンプルソースに、その対処法が書かれてました。それがこのデリゲートメソッドの処理でした。
なにこの意味不明の処理?と思ってたらバグ対策だったのねん。
注釈にzoomToRect:animated:メソッドの不具合対策て書かれてました。3.0の後のバージョンでは治るよとのこと。
もしかして3.0.1では治ってるかも。ま、シミュレータが3.0.1にならないと意味ないけど。
このメソッドは、ズーミング(上のズームバウンスアニメーションも含め)が完了した時に呼ばれるみたいです。センタリングとか、ズームング後の、こまごました調整をするにはここかな。
とかを加えると、なにやっても(縮小しても、拡大しても)等倍表示の状態に戻されるようにできる。
ユーザーの適当なズーミングで設定された倍率を、0.5、1.0、2.0とかいうふうにきっちりとした区切りに調整したりしたければ、ここらへんでやるとよさげ。ヘッダーで
を用意しておいて
こんな感じ。汎用性ゼロですがサンプルということで。
lastScaleはもちろん一番最初に1.0に初期化しておきます。
UIScrollViewの初期scale値は1.0なので、これだけでOKだけど、2.0から始めたいなら
ですな。
あと、せっかくなんでtestviewのフレームをずらして配置するとどうなるか試してみましたん。以下はlastScale = 1.0の等倍スケールスタートでテスト。
初期表示はこんな感じ。
たしかにframeの原点=(-300, -300)で指定してるから、これで正解ですな。
ただし、左上方向にはスクロールできません。それと右下が見えてるにもかかわらず、右下方向にスクロールできる。
これは、例えば横方向だと
ということで、180ピクセルだけスクロールできると計算されるみたい。
実際はすでに300ピクセル左にめり込んだ状態なので、スクロールしなくても全面見えているが、上記計算のために180ピクセル動くので、残り20ピクセルが残された状態までスクロールできるわけですわ。
で、ズームインアウトして1/2にしてみると
げえええ、消えたああああ。スクロールもできね~
となる。
縮小で、画像幅は
となったから画面内におさまると判断してスクロールできないみたいっす。
それと、一度ズーミングした後はtestViewの矩形の(0、0)以降の領域でスクロール範囲が再計算されるみたいで、ズームアウトして以下の状態に戻っても、今度はスクロールできなくなった。
testViewは、frameのoriginである(-300, -300)もスケーリングされて(-150, -150)になるかな~と想像してたんだけど、まったくスケーリングされないみたい。
なので幅が250になったtestViewは全面的に画面外になると...
となり、画面外にいっちゃうわけです。
確認のために
として表示させると
となって、ここでピンチオープンクローズでズームアウトすると
升目が増えてて1/2になっているのがわかるかな?
というふうに、(300、300)のオフセットはそのまま画像だけ1/2になる。
で、今回は
がスクロールできる範囲となるので、スクロールして全面表示できるぞっと。
ま、frameのoriginの設定は慎重にってことですな。
一緒にスクロールさせたいけど、ズームはさせたくないボタンビューを配置するとかに使うくらいかな~。それと、縮小表示時にUIScrollViewより小さくなったとき、埋め込まれたUIViewをセンタリングしたい時とか。
とすると
こんな感じで「?」ボタンが出ます。スクロールに連動。
ちなみにズームにまで連動させたければ
てやればいい。
追記)
とやれば、フローティング状態で常時左上に表示されるボタンにもなる。
ここらへん、みごとに親側UIView(この場合UIScrollView)のCTMが、子側UIView(この場合testView)に影響を及ぼしてるみたいです。CTMについては「iPhoneアプリ開発、その(64)」~「iPhoneアプリ開発、その(69)」あたりを参照。
これがtestViewを書き直してないのに、ズームされた画像が表示される理由でもある。
scrollViewDidEndZoomingメソッドに0.5倍の時はセンタリングするようにtestview.frameを調整して今回はおしまい。サンプルをたたき台に、いろいろ試してみてください。
次回こそタップ、ダブルタップ対応。
------------
サンプルプロジェクト:sc2.zip
scrollview.bounces = NO;
とすることで、ドラッグで範囲外までスクロールしてから戻るという動作(スクロールバウンスアニメーション)を禁止できます。こいつはデフォルトはYESです。
同じように
scrollview.bouncesZoom = YES;
で、ピンチで許可したズーム範囲外までズームを許してから範囲内に戻る(ズームバウンスアニメーション)という動作をゆるします。こっちは逆にデフォルトがNOみたいっす。
ズーム範囲を0.5~2.0(元々の0.1~10.0はいっぱいピンチしないと範囲外にいかないからね)あたりにして試してみてちょ。
で、触ってて気づいたのが、ズームアウト、こんな感じのところで手を離すとスクロールができなくなるんですわ、前回のサンプル。
右がはみ出てるのにスクロールできない。
なにこれ?
バグじゃんと思ったら、そのとおりでサンプルソースに、その対処法が書かれてました。それがこのデリゲートメソッドの処理でした。
- (void)scrollViewDidEndZooming:(UIScrollView *)scrollView
withView:(UIView *)view atScale:(float)scale {
[scrollView setZoomScale:scale+0.01 animated:NO];
[scrollView setZoomScale:scale animated:NO];
}
なにこの意味不明の処理?と思ってたらバグ対策だったのねん。
注釈にzoomToRect:animated:メソッドの不具合対策て書かれてました。3.0の後のバージョンでは治るよとのこと。
もしかして3.0.1では治ってるかも。ま、シミュレータが3.0.1にならないと意味ないけど。
このメソッドは、ズーミング(上のズームバウンスアニメーションも含め)が完了した時に呼ばれるみたいです。センタリングとか、ズームング後の、こまごました調整をするにはここかな。
[scrollView setZoomScale:1.0 animated:YES];
とかを加えると、なにやっても(縮小しても、拡大しても)等倍表示の状態に戻されるようにできる。
ユーザーの適当なズーミングで設定された倍率を、0.5、1.0、2.0とかいうふうにきっちりとした区切りに調整したりしたければ、ここらへんでやるとよさげ。ヘッダーで
double lastScale;
を用意しておいて
if (scale > lastScale) {
scale = lastScale * 2.0;
} else if (scale < lastScale) {
scale = lastScale / 2.0;
}
lastScale = scale;
[scrollView setZoomScale:scale animated:YES];
こんな感じ。汎用性ゼロですがサンプルということで。
lastScaleはもちろん一番最初に1.0に初期化しておきます。
lastScale = 1.0;
UIScrollViewの初期scale値は1.0なので、これだけでOKだけど、2.0から始めたいなら
lastScale = 2.0;
scrollview.zoomScale = lastScale;
ですな。
あと、せっかくなんでtestviewのフレームをずらして配置するとどうなるか試してみましたん。以下はlastScale = 1.0の等倍スケールスタートでテスト。
testview = [[testView alloc]
initWithFrame:CGRectMake(-300, -300, 500, 500)];
初期表示はこんな感じ。
たしかにframeの原点=(-300, -300)で指定してるから、これで正解ですな。
ただし、左上方向にはスクロールできません。それと右下が見えてるにもかかわらず、右下方向にスクロールできる。
これは、例えば横方向だと
500(内容部横ピクセル数) - 320(画面の横ピクセル数) = 180
ということで、180ピクセルだけスクロールできると計算されるみたい。
実際はすでに300ピクセル左にめり込んだ状態なので、スクロールしなくても全面見えているが、上記計算のために180ピクセル動くので、残り20ピクセルが残された状態までスクロールできるわけですわ。
で、ズーム
げえええ、消えたああああ。スクロールもできね~
となる。
縮小で、画像幅は
500 → 250
となったから画面内におさまると判断してスクロールできないみたいっす。
それと、一度ズーミングした後はtestViewの矩形の(0、0)以降の領域でスクロール範囲が再計算されるみたいで、ズームアウトして以下の状態に戻っても、今度はスクロールできなくなった。
testViewは、frameのoriginである(-300, -300)もスケーリングされて(-150, -150)になるかな~と想像してたんだけど、まったくスケーリングされないみたい。
なので幅が250になったtestViewは全面的に画面外になると...
となり、画面外にいっちゃうわけです。
確認のために
testview = [[testView alloc]
initWithFrame:CGRectMake(300, 300, 500, 500)];
として表示させると
となって、ここでピンチ
升目が増えてて1/2になっているのがわかるかな?
というふうに、(300、300)のオフセットはそのまま画像だけ1/2になる。
で、今回は
(300 + 250) - 320 = 230
がスクロールできる範囲となるので、スクロールして全面表示できるぞっと。
ま、frameのoriginの設定は慎重にってことですな。
一緒にスクロールさせたいけど、ズームはさせたくないボタンビューを配置するとかに使うくらいかな~。それと、縮小表示時にUIScrollViewより小さくなったとき、埋め込まれたUIViewをセンタリングしたい時とか。
UIButton* button = [UIButton buttonWithType:UIButtonTypeInfoLight];
button.frame = CGRectMake(10, 10, 20, 20);
[scrollview addSubview:button];
とすると
こんな感じで「?」ボタンが出ます。スクロールに連動。
ちなみにズームにまで連動させたければ
[testview addSubview:button];
てやればいい。
追記)
[self.view addSubview:button];
とやれば、フローティング状態で常時左上に表示されるボタンにもなる。
ここらへん、みごとに親側UIView(この場合UIScrollView)のCTMが、子側UIView(この場合testView)に影響を及ぼしてるみたいです。CTMについては「iPhoneアプリ開発、その(64)」~「iPhoneアプリ開発、その(69)」あたりを参照。
これがtestViewを書き直してないのに、ズームされた画像が表示される理由でもある。
scrollViewDidEndZoomingメソッドに0.5倍の時はセンタリングするようにtestview.frameを調整して今回はおしまい。サンプルをたたき台に、いろいろ試してみてください。
次回こそタップ、ダブルタップ対応。
------------
サンプルプロジェクト:sc2.zip