UIScrollView的contentSize属性,在AutoLayout下,UIScrollView的contentSize是由其内容的约束来定义的。
因此,在scrollView里面设置的约束不仅起到布局内容的作用,同时也定义scrollView可滚动范围的作用。
通过代码来演示:(自动布局用Masonry来做)
视图层级结构:view addSubView:scrollView addSubView:label
- (void)setupView {
[self.view addSubview:self.normalScrollView];
[self.normalScrollView addSubview:self.label];
[self.label mas_makeConstraints:^(MASConstraintMaker *make) {
//写法1,当通过leading和trailing的设定去约束
make.top.equalTo(self.normalScrollView.mas_top).mas_offset(50);
make.leading.equalTo(self.normalScrollView.mas_leading).mas_offset(20);
make.trailing.equalTo(self.normalScrollView.mas_trailing).mas_offset(-20);
make.height.mas_equalTo(50);
}];
}
- (UILabel *)label {
if (!_label) {
_label = [[UILabel alloc] initWithFrame:CGRectZero];
_label.text = @"测试Label测试";
_label.backgroundColor = [UIColor grayColor];
_label.textAlignment = NSTextAlignmentCenter;
}
return _label;
}
- (UIScrollView *)normalScrollView {
if (!_normalScrollView) {
_normalScrollView = [[UIScrollView alloc] initWithFrame:CGRectMake(20, 20, ScreenWidth-40, ScreenHeight-40)];
_normalScrollView.scrollEnabled = YES;
_normalScrollView.contentSize = CGSizeMake(ScreenWidth, ScreenHeight-40);
_normalScrollView.backgroundColor = [UIColor blueColor];
}
return _normalScrollView;
}
断点调试得到的结果:
<UIScrollView: 0x7faa3203e000; frame = (20 20; 335 627); contentSize: {150, 0}>
上面的代码可以看出,虽然已经设置了scrollView的contentSize,但是实际上在自动布局的情况下,contentSize的大小并不是原先设置的那样,而是由内容约束来定义的(leading,trailing
),后执行的Masonry布局代码重定义了contentSize。
因此,自动布局的情况下去定义contentSize是无效的。而mas_leading,mas_trailing
是根据contentSize来确定的具体位置,而不是根据scrollview的frame来确定,因此布局得到的并不是想要得到的结果。(相互依赖)
如果想要得到想要的效果,用Masonry对scrollView的子视图布局时最好采用以下写法:(下面的写法是在scrollView的frame写死的情况下)
[self.label mas_makeConstraints:^(MASConstraintMaker *make) {
//写法2,通过frame设定width去约束
make.top.equalTo(self.normalScrollView.mas_top).mas_offset(50);
make.leading.equalTo(self.normalScrollView.mas_leading).mas_offset(20);
make.width.mas_equalTo(self.normalScrollView.frame.size.width - 40);
make.height.mas_equalTo(50);
}];
此时能达到想要的效果,但是注意这里contentSize仍然是{0,0},可见contentSize需要leading,trailing
同时约束才会生效,未覆盖scrollView初始化时设置的contentSize。
contentSize的height同理,由top,bottom来决定,这里不作累述
所以,在Masonry中采用上述的写法,既能自定义滑动范围,不影响contentSize时很好的完成自动布局。