UIScrollView
の中にスクロールさせたいビュー(コンテンツ)を配置し、フィット表示させているときに、ナビゲーションバーなどの高さも考慮し、画面の中央にコンテンツを表示する方法について解説します。
この記事ではObjective-Cを使用していますが、Swiftでも同じ方法で実装可能です。
必要な処理
必要な処理は以下の通りです。
- スクロール対象のコンテンツビューを設定する。
UIScrollView
にインセット量の調整方法を設定する。- ズーム時にコンテンツビューのフレームを設定する。
- スクロールビューへのフィット処理を実装する。
- ビューコントローラのレイアウト時にフィット処理を実行する。
スクロール対象のコンテンツビューを設定する
スクロール対象のビューをこの記事ではコンテンツビューと呼びます。UIScrollView
にコンテンツビューを設定するには、UIScrollViewDelegate
の適合クラスのviewForZoomingInScrollView:
メソッドでコンテンツを返します。
- (UIView *)viewForZoomingInScrollView:(UIScrollView *)scrollView
{
return self.contentsView;
}
インセット量の調整方法を設定する
UIScrollViewでのインセット量の調整方法を設定します。以下のようにUIScrollView
のcontentInsetAdjustmentBehavior
プロパティをUIScrollViewContentInsetAdjustmentScrollableAxes
に設定します。
scrollView.contentInsetAdjustmentBehavior =
UIScrollViewContentInsetAdjustmentScrollableAxes;
ズーム時にコンテンツビューのフレームを設定する
ズーム倍率が変更されたときに、コンテンツビューのフレームサイズを変更する処理を実装します。スクロールビューよりもコンテンツビューの方が小さくなるときに、中央揃えになるように、フレームの左上の座標を調整するようにします。
- (void)scrollViewDidZoom:(UIScrollView *)scrollView
{
[self adjustContentFrameForScale:scrollView.zoomScale];
}
- (void)adjustContentFrameForScale:(CGFloat)zoomScale
{
// 等倍時の大きさを取得する。たとえば、プロパティに入れておく
CGSize contentSize = self.naturalContentSize;
// ズーム後のサイズを計算する
CGSize scaledSize = CGSizeMake(
contentSize.width * zoomScale,
contentSize.height * zoomScale);
// 中央揃えになるようにオフセットを計算する
CGSize scrollViewSize = self.scrollView.bounds.size;
CGFloat xOffset = MAX(0, (scrollViewSize.width - scaledSize.width) / 2);
CGFloat yOffset = MAX(0, (scrollViewSize.height - scaledSize.height) / 2);
// コンテンツビューのフレームを設定する
self.contentView.frame = CGRectMake(
xOffset,
yOffset,
scaledSize.width,
scaledSize.height
);
// スクロールビューに新しいサイズを設定する
self.scrollView.contentSize = scaledSize;
}
スクロールビューへのフィット処理を実装する
ここまでの実装で、スクロールビューよりもコンテンツビューの方が小さいときに、小さい辺は中央揃えされるようになります。更に、フィット倍率を計算して、フィットさせる処理も実装します。この処理を実行すると、コンテンツビューが画面の中央にフィット表示されます。
- (void)zoomToFit
{
// 等倍時の大きさを取得する。たとえば、プロパティに入れておく
CGSize contentSize = self.naturalContentSize;
// フィット倍率を計算する
CGSize scrollViewSize = self.scrollView.bounds.size;
CGFloat widthScale = scrollViewSize.width / contentSize.width;
CGFloat heightScale = scrollViewSize.height / contentSize.height;
// 小さい方の値を使用する
CGFloat minScale = MIN(widthScale, heightScale);
// スクロールビューに設定する
self.scrollView.minimumZoomScale = minScale;
self.scrollView.zoomScale = minScale;
// コンテンツビューのサイズを調整する
[self adjustContentFrameForScale:minScale];
}
ビューコントローラのレイアウト時にフィット処理を実行する
ビューコントローラが表示されるときや、デバイスの回転時、iPadのスプリットビューの状態変更などにより、ビューコントローラのサイズが変わるときに、追従してフィットさせるには、以下のように、viewWillLayoutSubviews
でフィット処理を実行します。
- (void)viewWillLayoutSubviews
{
[super viewWillLayoutSubviews];
// スクロールビューのサイズを設定する
self.scrollView.frame = self.view.bounds;
// フィットさせる
[self zoomToFit];
}