考虑一个带有单个子视图的UIScrollView
。子视图是一个UIImageView
,具有以下大小限制:
UIScrollView
的高度。UIImageView
的高度成比例缩放的图像宽度。预计UIImageView
的宽度将大于UIScrollView的宽度,因此需要滚动。
可以在viewDidLoad
(如果缓存)或异步期间设置图像。
如何使用autolayout实现上述功能,尽可能多地使用Interface builder?
基于这个answer我配置我的笔尖像这样:
UIScrollView
固定在其超视图的边缘。UIImageView
固定在UIScrollView
的边缘。UIImageView
具有占位符内在大小(以避免Scrollable Content Size Ambiguity错误)正如所料,结果是UIImageView
的大小与UIImage
的大小相同,而UIScrollView
水平和垂直滚动(因为图像比UIScrollView
大)。
然后我尝试了各种不起作用的东西:
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;
}
我正在努力转向自动布局,但这并不容易。
在autolayout制度下,理想情况下,UIScrollView contentSize仅由约束决定,而不是在代码中明确设置。
所以在你的情况下:
UIScrollView
。约束必须确保子视图和滚动视图之间的边距为0.我看到你已经尝试过这个。UIImageView
的内在大小决定了它的高度和宽度。在设计时,此大小只是一个占位符,以保持Interface Builder的快乐。在运行时,它将设置为实际图像大小,但这不是您想要的。viewDidLayoutSubviews
期间,将约束更新为实际内容大小。您可以通过更改高度和宽度约束的constant
属性,或调用setNeedsUpdateConstraints
并覆盖updateConstraints
来执行相同操作。这确保了系统可以仅从约束中导出contentSize
。
我已经完成了上述工作,它可以在iOS 6和7上使用UIScrollView
和自定义子视图可靠地工作,所以它也适用于UIImageView
。特别是如果你没有将子视图固定到滚动视图,iOS 6中的缩放将是紧张的。
您也可以尝试创建直接引用滚动视图的高度和宽度的倍数的高度和宽度约束,但我还没有尝试过这种其他方法。
只有在代码中实例化视图时才需要translatesAutoresizingMaskIntoConstraints
。如果您在IB中实例化它,则默认情况下禁用它
在我看来,UIImageView
应该填补ScrollView
。稍后我会尝试将scrollview
的缩放设置为适合您的值,这样图像只能向一个方向平移
在我的情况下,它是一个全宽UIImageView有一个定义的高度约束导致问题。
我在UIImageView上设置了另一个约束,其宽度与UIScrollView的宽度相匹配,因为它在界面构建器中然后添加了一个出口到UIViewController:
@property (weak, nonatomic) IBOutlet NSLayoutConstraint *imageViewWidthConstraint;
然后在viewDidLayoutSubviews上我更新了约束:
- (void) viewDidLayoutSubviews {
[super viewDidLayoutSubviews];
self.imageViewWidthConstraint.constant = CGRectGetWidth(self.scrollView.frame);
}
这似乎可以解决问题。