使用自动布局缩放UIImageView的UIScrollView
考虑一个具有单个子视图的UIScrollView
。 子视图是具有以下大小约束的UIImageView
:
- 它的高度必须等于
UIScrollView
的高度。 - 它的宽度必须是图像的宽度,与
UIImageView
的高度成比例。
预计UIImageView
的宽度将比UIScrollView的宽度大,因此需要滚动。
该图像可能会在viewDidLoad
(如果caching)或asynchronous时设置。
你如何使用自动布局实现上述function,尽可能多地使用Interface Builder?
到目前为止我所做的
基于这个答案,我configuration我的笔尖是这样的:
-
UIScrollView
固定在其超视图的边缘。 -
UIImageView
固定在UIScrollView
的边缘。 -
UIImageView
具有占位符的固有大小(以避免可滚动内容大小歧义错误)
正如所料,结果是UIImageView
的大小为UIImage
的大小,并且UIScrollView
水平和垂直滚动(因为图像大于UIScrollView
)。
然后我尝试了各种不起作用的东西:
- 在手动加载图像后设置
UIImageView
的框架。 - 在UIImageView的宽度上添加一个约束,并在载入图像后修改它的值。 这使图像更大(?!)。
- 图像加载后设置
zoomScale
。 没有明显的效果。
没有自动布局
以下代码完全按照我的要求,尽pipe没有自动布局或界面生成器。
- (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; }
我努力想要自动布局,但这并不容易。
在自动布局机制下,理想情况下,UIScrollView contentSize完全由约束决定,而不是在代码中明确设置。
所以在你的情况下:
-
创build约束来将子视图固定到
UIScrollView
。 约束必须确保子视图和滚动视图之间的边距为0.我看到你已经试过这个。 -
为您的子视图创build一个高度和宽度约束。 否则,
UIImageView
的内在大小决定了其高度和宽度。 在devise时,这个大小只是一个占位符来保持Interface Builder的快乐。 在运行时,它将被设置为实际的图像大小,但这不是你想要的。 -
在
viewDidLayoutSubviews
期间,将约束更新为实际的内容大小。 你可以直接通过改变高度和宽度约束的constant
属性,或者调用setNeedsUpdateConstraints
和覆盖updateConstraints
来做同样的事情。
这确保系统可以仅从约束派生contentSize
。
我已经完成了上述工作,它可以在iOS 6和7上使用UIScrollView
和自定义子视图可靠地工作,因此它也可以用于UIImageView
。 特别是如果你不把子视图固定在滚动视图上,在iOS 6中缩放将会不安。
您也可以尝试创build直接引用滚动视图的高度和宽度的倍数的高度和宽度约束,但是我没有尝试使用其他方法。
只有当您在代码中实例化视图时才需要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); }
这似乎是诀窍。
- 为UIScrollView设置约束
- 我有一个UILabel自动布局定位在屏幕上,但是当我隐藏导航栏,它会导致标签“抽搐”第二个
- Autolayout UILabel在第二视图出现时高度发生变化
- 调整UITableView头并包含UITextView(iOS7 + AutoLayout)
- UITableView tableFooterView显示在UITableView的顶部 – 错误
- iOS 8:UITableViewCell.contentView不调整其中的子视图
- 带有AutoLayout的UICollectionView Cell + UiLabel
- iOS滚动视图,容器视图 – 自动布局问题
- 组表TableView,使用自调整节标题,重新加载后,如果向上滚动,tableview将跳转