使用自动布局在UIScrollView中缩放UIImageView

19

我有一个UIImageView嵌入到UIScrollView中,在iOS 6和自动布局之前,我使用以下代码片段在控制器的viedDidLoad方法内显示可滚动和可缩放的图像。

self.scrollView.contentSize = self.imageView.image.size;
self.imageView.frame = CGRectMake(0, 0, self.imageView.image.size.width, self.imageView.image.size.height);

但现在故事板中设置的约束条件被使用。我发现这个问题在这里以及其他一些关于SO的文章指出,约束会在viewDidLoad后加载/执行,将之前的代码移到viewDidAppear可以解决这个问题,但是缩放功能无法正常工作,而且似乎scrollView和imageView的大小在捏合缩放手势后会重新设置为storyboard的约束条件。

我只是猜测,但我认为如果有一种方法可以在代码中覆盖scrollView和imageView的垂直和水平空间约束,那可能会起作用。

还有其他人遇到这个问题吗?

3个回答

14

Zsolt在评论中提出了最佳解决方案:

http://github.com/evgenyneu/ios-imagescroll 看看这个。对我来说完美地运作。

该存储库中提出的解决方案是在显示图像之前调整最小和当前缩放级别:

    @interface MyViewController () <UIScrollViewDelegate>
    @property (weak, nonatomic) IBOutlet UIScrollView *scrollView;
    @property (weak, nonatomic) IBOutlet UIImageView *imageView;
    @end


    @implementation MyViewController

    - (void)viewDidLoad
    {
      [super viewDidLoad];
      self.scrollView.delegate = self;
      
      [self initZoom];
    }
    - (void)didRotateFromInterfaceOrientation:(UIInterfaceOrientation)fromInterfaceOrientation
    {
      [self initZoom];
    }

    // Zoom to show as much image as possible
    - (void) initZoom {
      float minZoom = MIN(self.view.bounds.size.width / self.imageView.image.size.width,
                          self.view.bounds.size.height / self.imageView.image.size.height);
      if (minZoom > 1) return;
      
      self.scrollView.minimumZoomScale = minZoom;
      
      self.scrollView.zoomScale = minZoom;
    }

    - (UIView*)viewForZoomingInScrollView:(UIScrollView *)scrollView
    {
      return self.imageView;
    }

然而,示例在缩小时存在居中问题。图像没有被居中。可以通过使用自定义滚动视图类并在其中使用以下代码轻松解决此问题:

但是,样本存在缩小时无法居中的问题。图像未被置中。这可以通过使用具有以下代码的自定义滚动视图类轻松解决:

    @interface MyScrollView : UIScrollView
    @end

    @implementation MyScrollView

    -(void)layoutSubviews
    {
      [super layoutSubviews];
      UIView* v = [self.delegate viewForZoomingInScrollView:self];
      CGFloat svw = self.bounds.size.width;
      CGFloat svh = self.bounds.size.height;
      CGFloat vw = v.frame.size.width;
      CGFloat vh = v.frame.size.height;
      CGRect f = v.frame;
      if (vw < svw)
        f.origin.x = (svw - vw) / 2.0;
      else
        f.origin.x = 0;
      if (vh < svh)
        f.origin.y = (svh - vh) / 2.0;
      else
        f.origin.y = 0;
      v.frame = f;
    }

    @end

只是提供信息,您提供的项目链接已过时,并且已经更新为Swift版本 = https://github.com/evgenyneu/ios-imagescroll-swift - Daniel Galasko

7

这样做更好,但是当我缩小图像时,它会居中于滚动视图的左上角,而不是在中心(或者说不是将图像的角落放在原点)。另外请注意,示例具有IBOutletCollection用于约束,必须包括UIImageView上的所有约束,否则在缩放时会出现异常。 - webjprgm
2
我通过关闭translatesAutoresizingMaskIntoConstraints并在viewWillLayoutSubviews中将框架原点设置为0,0来解决了我的问题。 图像不是居中的,但至少在缩放时不会再滑出可滚动区域了。 - webjprgm
我使用了[_imgProduct setCenter:_scrProduct.center];而不是0,0和translatesAutoresizingMaskIntoConstraints = NO; - Zsolt
12
请查看这个链接:https://github.com/evgenyneu/ios-imagescroll。对我来说功能完美。 - Zsolt

5

我也同意Zsolt的建议和链接。

但是,我更新了宽度/高度的限制,以便能够处理任何大小的图片:

- (void) initZoom
{
    for (NSLayoutConstraint *constraint in self.photoImageView.constraints)
    {
      if (constraint.firstAttribute == NSLayoutAttributeWidth)
        constraint.constant = self.photoImageView.image.size.width;
      else if (constraint.firstAttribute == NSLayoutAttributeHeight)
        constraint.constant = self.photoImageView.image.size.height;
    }
    
    float minZoom = MIN(self.scrollView.bounds.size.width / self.photoImageView.image.size.width,
                        self.scrollView.bounds.size.height / self.photoImageView.image.size.height);
    if (minZoom > 1) return;

    self.scrollView.minimumZoomScale = minZoom;
    
    self.scrollView.zoomScale = minZoom;
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接