UIScrollView使用自动布局缩放UIImageView

hpi*_*que 11 interface-builder uiscrollview uiimageview ios autolayout

UIScrollView与UIImageView

考虑UIScrollView使用单个子视图.子视图UIImageView具有以下大小限制:

  • 它的高度必须等于高度UIScrollView.
  • 它的宽度必须是与图像的高度成比例缩放的图像宽度UIImageView.

预计宽度UIImageView将大于UIScrollView的宽度,因此需要滚动.

图像可能在viewDidLoad(如果缓存)或异步期间设置.

如何使用autolayout实现上述功能,尽可能多地使用Interface builder?

到目前为止我做了什么

根据这个答案,我配置了我的笔尖:

  • UIScrollView被钉到它的父的边缘.
  • UIImageView被钉到的边缘UIScrollView.
  • UIImageView有一个占位符固有大小(以避免滚动的内容大小歧义错误)

正如预期的那样,结果是UIImageView大小UIImageUIScrollView水平和垂直的大小相同(因为图像大于UIScrollView).

然后我尝试了各种不起作用的东西:

  • 手动加载图像后设置框架UIImageView.
  • 为UIImageView的宽度添加约束,并在加载图像后修改其值.这使图像更大(?!).
  • zoomScale加载图像后设置.没有明显的效果.

没有自动布局

以下代码完全按照我的意愿执行,尽管没有自动布局或界面构建器.

- (void)viewDidLoad
{
    {
        UIScrollView *scrollView = [[UIScrollView alloc] initWithFrame:CGRectMake(0, 0, self.view.frame.size.width, self.view.frame.size.height)];
        scrollView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
        [self.view addSubview:scrollView];
        self.scrollView = scrollView;
    }

    {
        UIImageView *imageView = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, self.scrollView.frame.size.width, self.scrollView.frame.size.height)];
        imageView.contentMode = UIViewContentModeScaleAspectFit;
        imageView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
        [self.scrollView addSubview:imageView];
        self.scrollView.contentSize = imageView.frame.size;
        self.imageView = imageView;
    }
}

- (void)viewDidLayoutSubviews
{
    [super viewDidLayoutSubviews];
    [self layoutStripImageView];
}

- (void)layoutStripImageView
{ // Also called when the image finishes loading
    UIImage *image = self.imageView.image;
    if (! image) return;

    const CGSize imageSize = image.size;
    const CGFloat vh = self.scrollView.frame.size.height;
    const CGFloat scale = vh / imageSize.height;
    const CGFloat vw = imageSize.width * scale;

    CGSize imageViewSize = CGSizeMake(vw, vh);
    self.imageView.frame = CGRectMake(0, 0, imageViewSize.width, imageViewSize.height);
    self.scrollView.contentSize = imageViewSize;
}
Run Code Online (Sandbox Code Playgroud)

我正在努力转向自动布局,但这并不容易.

Gle*_*Low 11

在autolayout制度下,理想情况下,UIScrollView contentSize仅由约束决定,而不是在代码中明确设置.

所以在你的情况下:

  • 创建约束以将子视图固定到UIScrollView.约束必须确保子视图和滚动视图之间的边距为0.我看到你已经尝试过这个.

  • 为子视图创建高度和宽度约束.否则,其内在大小UIImageView决定了它的高度和宽度.在设计时,此大小只是一个占位符,以保持Interface Builder的快乐.在运行时,它将设置为实际图像大小,但这不是您想要的.

  • 在此期间viewDidLayoutSubviews,将约束更新为实际内容大小.您可以通过更改constant高度和宽度约束的属性直接执行此操作,也可以通过调用setNeedsUpdateConstraints和覆盖updateConstraints来执行此操作.

这确保了系统可以contentSize仅从约束中获得.

我已经完成了上述工作,它在iOS 6和7上可靠地运行,UIScrollView并且具有自定义子视图,因此它也应该可以工作UIImageView.特别是如果你没有将子视图固定到滚动视图,iOS 6中的缩放将是紧张的.

您也可以尝试创建直接引用滚动视图的高度和宽度的倍数的高度和宽度约束,但我还没有尝试过这种其他方法.


小智 2

translatesAutoresizingMaskIntoConstraints仅当您在代码中实例化视图时才需要。如果您在 IB 中实例化它,则默认情况下它是禁用的

我认为UIImageView应该填写ScrollView. 稍后我会尝试将 的缩放设置scrollview为适合您的值,这样图像只能沿一个方向平移