场景:
一个storyboard里放着一个UIViewController,在其view上放了一个UIScrollView,然后里面放了很多控件,并且已经布局好了,然后点击里面的加号按钮,会添加一个一样的控件进来,如图
9CA0864B-D191-4056-B5B6-2AF88E58C683.png
Snip20161125_5.png
初步想法,是改变之前storyboard中的一个约束,拉长并放入自定义的xib的view,由于单词太长,后面简称sb。
Snip20161125_6.png Snip20161125_7.png/**
原来 界面上的加号按钮事件
*/
- (IBAction)didTapAddBtn:(UIButton *)sender {
// 加一个AddTest到界面上
AddTest *addView = [AddTest viewFromXib];
[self.scrollView addSubview:addView];
__block int addViewCount = 0;
[self.scrollView.subviews enumerateObjectsUsingBlock:^(__kindof UIView * _Nonnull subV, NSUInteger idx, BOOL * _Nonnull stop) {
if ([subV isKindOfClass:NSClassFromString(@"AddTest")]) {
addViewCount ++;
}
}];
// 第一个
if (addViewCount == 1) {
// 这个是之前两个控件之前的垂直约束,我们只有把这个垂直约束变大了,才能放入自定义xib,位置更合理
self.nextViewToAddBtnVerticalConstraint.constant = 12+12+44;
// 新添加 的view的顶部跟之前有加号那个view的底部垂直间距为12
NSLayoutConstraint *verticalToOriginAddViewBottom =
[NSLayoutConstraint constraintWithItem:addView
attribute:NSLayoutAttributeTop
relatedBy:NSLayoutRelationEqual
toItem:self.originAddView
attribute:NSLayoutAttributeBottom
multiplier:1.0
constant:12];
// 新添加 的view的顶部跟之前有加号那个view的左边一样
NSLayoutConstraint *leading =
[NSLayoutConstraint constraintWithItem:addView
attribute:NSLayoutAttributeLeading
relatedBy:NSLayoutRelationEqual
toItem:self.originAddView
attribute:NSLayoutAttributeLeading
multiplier:1.0
constant:0];
// 新添加 的view的顶部跟之前有加号那个view的右边一样
NSLayoutConstraint *trailing =
[NSLayoutConstraint constraintWithItem:addView
attribute:NSLayoutAttributeTrailing
relatedBy:NSLayoutRelationEqual
toItem:self.originAddView
attribute:NSLayoutAttributeTrailing
multiplier:1.0
constant:0];
// 新添加 的view的高度为44,之前有加号那个view也是44
NSLayoutConstraint *heigth =
[NSLayoutConstraint constraintWithItem:addView
attribute:NSLayoutAttributeHeight
relatedBy:NSLayoutRelationEqual
toItem:nil
attribute:NSLayoutAttributeNotAnAttribute
multiplier:0.0
constant:44];
// 自身约束添加到自身上
[addView addConstraint:heigth];
// 非自身约束,子控件与子控件之间的相对约束,添加到大家的父控件上
[self.scrollView addConstraints:@[verticalToOriginAddViewBottom, leading, trailing]];
} else {
// 不是第一个
}
}
运行,点击加号,问题来了,scrollview显示不正常,添加的xib的view也不正常,宽度也不对。
Snip20161125_8.png反复查看,约束正确也与,无非就是vertical leading trailing 自身高度44约束 啊,没有问题,然后不用代码加这个控件,直接在storyboard中添加这个控件。
跟代码的约束一样。
自身高度约束44
然后leading trailing相同,vertical为12,也跟代码约束一样。
Snip20161125_12.png奇怪同样的约束,用代码添加就不行,在IB中添加就正常,如图,在IB中添加view正常。
Snip20161125_13.png那么问题来了,代码添加约束跟在IB直接托约束的区别在哪里,肯定是这个区别导致了这个不正常的问题。其实,那会儿点加号,是有打印的。如图。
Snip20161125_14.png跳到UIView头文件会发现一个属性
/* By default, the autoresizing mask on a view gives rise to constraints that fully determine
the view's position. This allows the auto layout system to track the frames of views whose
layout is controlled manually (through -setFrame:, for example).
When you elect to position the view using auto layout by adding your own constraints,
you must set this property to NO. IB will do this for you.
*/
@property(nonatomic) BOOL translatesAutoresizingMaskIntoConstraints NS_AVAILABLE_IOS(6_0); // Default YES
谷歌翻译
默认情况下,视图上的自动调整掩码会产生完全确定的约束
视图的位置。 这允许自动布局系统跟踪视图的帧
布局是手动控制的(例如通过-setFrame:)。
当您通过添加自己的约束选择使用自动布局定位视图时,
您必须将此属性设置为NO。 IB会为你做这个。
最后一句话, IB会为你做这个。是重点。
然后, 我们给addView加上这个属性。
/**
原来 界面上的加号按钮事件
*/
- (IBAction)didTapAddBtn:(UIButton *)sender {
// 加一个AddTest到界面上
AddTest *addView = [AddTest viewFromXib];
addView.translatesAutoresizingMaskIntoConstraints = NO;// 这里加上
[self.scrollView addSubview:addView];
再次运行,正常。
其他解决方案。
[addView mas_makeConstraints:^(MASConstraintMaker *make) {
make.leading.trailing.height.equalTo(self.originAddView);
make.top.equalTo(self.originAddView.mas_bottom).offset(12);
}];
总结:
当把一个xib放入一个有autolayout的view上,一定要把这个xib的view的translatesAutoresizingMaskIntoConstraints设置成NO;
网友评论