1. ホーム
  2. ios

[解決済み] UIScrollViewを小さくするとコンテンツが中央に配置される

2022-04-28 21:13:24

質問

私は UIImageView の中に UIScrollView これは、ズームとスクロールに使用しています。スクロールビューの画像/コンテンツがスクロールビューより大きい場合、すべてがうまく機能します。しかし、画像がスクロールビューより小さくなると、スクロールビューの左上隅に貼り付いてしまいます。写真アプリのように中央に表示させたいのですが。

の内容を保持するためのアイデアや例があれば教えてください。 UIScrollView を小さくすると中央に配置されるのでしょうか?

iPhone 3.0で作業しています。

以下のコードでほぼ動作します。最小ズームレベルに達した後、画像をピンチすると左上隅に戻ります。

- (void)loadView {
    [super loadView];

    // set up main scroll view
    imageScrollView = [[UIScrollView alloc] initWithFrame:[[self view] bounds]];
    [imageScrollView setBackgroundColor:[UIColor blackColor]];
    [imageScrollView setDelegate:self];
    [imageScrollView setBouncesZoom:YES];
    [[self view] addSubview:imageScrollView];

    UIImageView *imageView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"WeCanDoIt.png"]];
    [imageView setTag:ZOOM_VIEW_TAG];
    [imageScrollView setContentSize:[imageView frame].size];
    [imageScrollView addSubview:imageView];

    CGSize imageSize = imageView.image.size;
    [imageView release];

    CGSize maxSize = imageScrollView.frame.size;
    CGFloat widthRatio = maxSize.width / imageSize.width;
    CGFloat heightRatio = maxSize.height / imageSize.height;
    CGFloat initialZoom = (widthRatio > heightRatio) ? heightRatio : widthRatio;

    [imageScrollView setMinimumZoomScale:initialZoom];
    [imageScrollView setZoomScale:1];

    float topInset = (maxSize.height - imageSize.height) / 2.0;
    float sideInset = (maxSize.width - imageSize.width) / 2.0;
    if (topInset < 0.0) topInset = 0.0;
    if (sideInset < 0.0) sideInset = 0.0;
    [imageScrollView setContentInset:UIEdgeInsetsMake(topInset, sideInset, -topInset, -sideInset)];
}

- (UIView *)viewForZoomingInScrollView:(UIScrollView *)scrollView {
    return [imageScrollView viewWithTag:ZOOM_VIEW_TAG];
}

/************************************** NOTE **************************************/
/* The following delegate method works around a known bug in zoomToRect:animated: */
/* In the next release after 3.0 this workaround will no longer be necessary      */
/**********************************************************************************/
- (void)scrollViewDidEndZooming:(UIScrollView *)scrollView withView:(UIView *)view atScale:(float)scale {
    [scrollView setZoomScale:scale+0.01 animated:NO];
    [scrollView setZoomScale:scale animated:NO];
    // END Bug workaround

    CGSize maxSize = imageScrollView.frame.size;
    CGSize viewSize = view.frame.size;
    float topInset = (maxSize.height - viewSize.height) / 2.0;
    float sideInset = (maxSize.width - viewSize.width) / 2.0;
    if (topInset < 0.0) topInset = 0.0;
    if (sideInset < 0.0) sideInset = 0.0;
    [imageScrollView setContentInset:UIEdgeInsetsMake(topInset, sideInset, -topInset, -sideInset)];
}

解決方法は?

現在、サブクラス化した UIScrollView をオーバーライドし setContentOffset: に基づいてオフセットを調整します。 contentSize . ピンチ操作とプログラムによるズームの両方で動作します。

@implementation HPCenteringScrollView

- (void)setContentOffset:(CGPoint)contentOffset
{
    const CGSize contentSize = self.contentSize;
    const CGSize scrollViewSize = self.bounds.size;

    if (contentSize.width < scrollViewSize.width)
    {
        contentOffset.x = -(scrollViewSize.width - contentSize.width) / 2.0;
    }

    if (contentSize.height < scrollViewSize.height)
    {
        contentOffset.y = -(scrollViewSize.height - contentSize.height) / 2.0;
    }

    [super setContentOffset:contentOffset];
}

@end

このコードは短くて簡単なうえに、@Erdemusのソリューションよりもずっとスムーズなズームを実現します。このコードが実際に使われているのは RMGallery のデモをご覧ください。