6

我需要有关 UIScrollView 示例的帮助。

我创建了一个简单的程序来滚动和缩放内容 ( UIImageView)。它工作正常,除了当我尝试缩小时内容经常消失在右下角。但是由于我设置minimumZoomScale为1.0f,实际上并没有缩小,只是内容跳出了视图。更奇怪的是,在此之后我无法向上滚动。显然内容大小也搞砸了。

在此处输入图像描述

我在示例代码中的设置如下图所示。

在此处输入图像描述

当我(尝试)缩小后检查状态时,我发现了两个错误的地方。

  • _scrollView.contentSize为 480x360,不应小于 1000x1000
  • _scrollView.bounds以某种方式跳到顶部(即,_scrollView.bounds.origin.y始终为 0)

为了应对上述两项,我在 UIScrollViewDelegate 中添加了以下代码,现在它可以正常工作了。

- (void)scrollViewWillBeginZooming:(UIScrollView *)scrollView withView:(UIView *)view
{
    if(scrollView == _scrollView && view == _contentView)
    {
        // Setting ivars for scrollViewDidZoom
        _contentOffsetBeforeZoom = _scrollView.contentOffset;
        _scrollViewBoundsBeforeZoom = _scrollView.bounds;
    }
}

- (void)scrollViewDidZoom:(UIScrollView *)scrollView
{
    if(scrollView == _scrollView)
    {
        // If you zoom out, there are cases where ScrollView content size becomes smaller than original,
        // even though minimum zoom scale = 1. In that case, it will mess with the contentOffset as well.
        if(_scrollView.contentSize.width < CONTENT_WIDTH || _scrollView.contentSize.height < CONTENT_HEIGHT)
        {
            _scrollView.contentSize = CGSizeMake(CONTENT_WIDTH, CONTENT_HEIGHT);
            _scrollView.contentOffset = _contentOffsetBeforeZoom;
        }

        // If you zoom out, there are cases where ScrollView bounds goes outsize of contentSize rectangle.
        if(_scrollView.bounds.origin.x + _scrollView.bounds.size.width > _scrollView.contentSize.width ||
           _scrollView.bounds.origin.y + _scrollView.bounds.size.height > _scrollView.contentSize.height)
        {
            _scrollView.bounds = _scrollViewBoundsBeforeZoom;
        }            
    }
}

然而,有必要归结为这一点吗?这是一个非常简单的序列,很难相信苹果需要我们付出这样的努力。所以,我敢打赌我在这里遗漏了一些东西......

以下是我的原始代码。请帮我找出我做错了什么(或遗漏了什么)!

#define CONTENT_WIDTH 1000
#define CONTENT_HEIGHT 1000

  >>>> Snip >>>>

- (void)viewDidLoad
{
    [super viewDidLoad];
    // Do any additional setup after loading the view, typically from a nib.

    _scrollView = [[UIScrollView alloc] initWithFrame:CGRectMake(0, 0, 320, 460)];
    _scrollView.contentSize = CGSizeMake(CONTENT_WIDTH, CONTENT_HEIGHT);
    _scrollView.backgroundColor = [UIColor blueColor];
    _scrollView.maximumZoomScale = 8.0f;
    _scrollView.minimumZoomScale = 1.0f;
    _scrollView.indicatorStyle = UIScrollViewIndicatorStyleWhite;
    _scrollView.scrollEnabled = YES;
    _scrollView.delegate = self;
    [self.view addSubview:_scrollView];

    _contentView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"sample.jpg"]]; // sample.jpg is 480x360
    CGPoint center = (CGPoint){_scrollView.contentSize.width / 2, _scrollView.contentSize.height / 2};
    _contentView.center = center;
    [_scrollView addSubview:_contentView];

    _scrollView.contentOffset = (CGPoint) {center.x - _scrollView.bounds.size.width / 2, center.y - _scrollView.bounds.size.height / 2};        
}

- (UIView *) viewForZoomingInScrollView:(UIScrollView *)scrollView
{
    if(scrollView == _scrollView)
    {
        return _contentView;
    }
    return nil;
}
4

4 回答 4

12

我创建了一个快速示例项目,并遇到了您使用粘贴的代码描述的相同问题。我不完全知道在 iOS 中“正确”的缩放方式是什么,但我发现这个教程说你需要在缩放滚动视图后重新定位你的 contentView。我个人希望它会自动重新居中,因为它是您在 viewForZoomingInScrollView 委托方法中返回的视图,但显然不是。

- (void)centerScrollViewContents {
    CGSize boundsSize = _scrollView.bounds.size;
    CGRect contentsFrame = _contentView.frame;

    if (contentsFrame.size.width < boundsSize.width) {
        contentsFrame.origin.x = (boundsSize.width - contentsFrame.size.width) / 2.0f;
    } else {
        contentsFrame.origin.x = 0.0f;
    }

    if (contentsFrame.size.height < boundsSize.height) {
        contentsFrame.origin.y = (boundsSize.height - contentsFrame.size.height) / 2.0f;
    } else {
        contentsFrame.origin.y = 0.0f;
    }

    _contentView.frame = contentsFrame;
}

- (void)scrollViewDidZoom:(UIScrollView *)scrollView {
    // The scroll view has zoomed, so we need to re-center the contents
    [self centerScrollViewContents];
}

上面的代码不是我写的,只是从教程中复制过来的。我认为它非常简单。此外,将 contentView 居中似乎要优雅得多,然后不断更改滚动视图的边界和内容大小,因此请尝试一下。

于 2012-09-09T04:12:49.083 回答
1

如果有人在缩小结果背景以显示时遇到弹跳问题,请尝试在 Interface Builder 中删除弹跳(弹跳缩放)。

于 2015-05-07T14:43:17.330 回答
1

我能够使用在缩放后调整速率的代表答案来解决这个问题......但后来我记得我正在使用自动布局,并且只是添加了水平和垂直居中的约束(除了将图像绑定到的约束之外滚动视图的每个边缘)在不使用委托方法的情况下为我解决了这个问题。

于 2016-11-17T18:04:06.523 回答
0

奥尔尚斯克迅速回答 5

    func scrollViewDidZoom(_ scrollView: UIScrollView) {
        centerScrollViewContents()
    }
    
    func centerScrollViewContents() {
        let boundsSize = scrollView.bounds.size;
        var contentsFrame = container.frame;

        if (contentsFrame.size.width < boundsSize.width) {
            contentsFrame.origin.x = (boundsSize.width - contentsFrame.size.width) / 2.0;
        } else {
            contentsFrame.origin.x = 0.0;
        }

        if (contentsFrame.size.height < boundsSize.height) {
            contentsFrame.origin.y = (boundsSize.height - contentsFrame.size.height) / 2.0;
        } else {
            contentsFrame.origin.y = 0.0;
        }

        container.frame = contentsFrame;
    }
于 2020-09-09T08:42:36.143 回答