根据Apple的说法,我们可以通过向滚动视图之外的内容添加约束来在滚动视图中创建浮动视图。
请注意,您可以使滚动视图的子视图显示为浮动 (不滚动)通过创建约束来覆盖其他滚动内容 在视图和滚动视图的子树之外的视图之间,例如 滚动视图的超级视图。
在滚动视图中创建锚定视图
您可能会发现要在滚动视图中创建一个区域,当用户滚动滚动视图的内容时,该区域不会移动。您可以使用单独的容器视图来完成此操作。
在滚动视图滚动之前创建约束时(例如通过Interface Builder),这很有效,但是如果我在滚动滚动视图后尝试创建所述约束,则会得到错误定位的视图。
如果滚动滚动视图后,如何以编程方式创建此锚定或浮动约束?
我使用以下代码安装约束:
NSLayoutConstraint *constraint = [NSLayoutConstraint constraintWithItem:self.pinkView
attribute:NSLayoutAttributeBottom
relatedBy:NSLayoutRelationEqual
toItem:self.scrollViewContainer
attribute:NSLayoutAttributeBottom
multiplier:1
constant:0];
[self.scrollViewContainer addConstraint:constraint];
这就是我想要的样子:
(注意粉红色视图如何与青色视图垂直对齐。)
但是,如果用户滚动然后点击按钮,则最终结果如下:
答案 0 :(得分:2)
TLDR:浮动约束的特殊之处在于它们在滚动滚动视图时不断更新其常量属性。因此,在创建约束时,必须通过预先填充常量以等于滚动视图的内容偏移值来确保与滚动视图同步。
在最简单的示例中,假设我们有一个带按钮的滚动视图。点击按钮时,滚动视图中应显示浮动视图。
如果用户在点击按钮之前滚动,则浮动视图将无法正确对齐。
问题在于,当您通过约束创建浮动视图时,您将创建一个特殊约束,当滚动视图滚动时,该约束将不断更新其常量值。 (其他约束永远不会随着事物的移动而更新它们的常量值。)当您最初创建约束时,常量值初始化为0,因此不知道到目前为止滚动视图发生了什么。自动布局没有机会与滚动视图同步,因为之前没有安装它,因此无法通过自动布局来了解它。
在滚动之前安装约束时它的工作原因是因为它安装在0,然后自动布局会自动更新它的常量。因此,你不小心"安装约束并将其与滚动视图同步(因为偏移量从0开始)。
通过覆盖scrollViewDidScroll:,我们可以看到此自动更新常量的证据:
Constraint constant: 95.00
Constraint constant: 98.50
Constraint constant: 101.50
Constraint constant: 105.50
Constraint constant: 106.50
解决方案是安装约束,并将常量属性设置为当前滚动视图偏移量:
NSLayoutConstraint *constraint = [NSLayoutConstraint constraintWithItem:self.pinkView
attribute:NSLayoutAttributeBottom
relatedBy:NSLayoutRelationEqual
toItem:self.scrollViewContainer
attribute:NSLayoutAttributeBottom
multiplier:1
constant:self.scrollView.contentOffset.y];
[self.scrollViewContainer addConstraint:constraint];
其他有趣的事情需要注意:
另一种思考方式就是这样:
自动布局很愚蠢。除了滚动视图的相对值之外,无法将浮动视图的位置设置为任何其他值。因此,Apple能够通过做一些棘手的事情来伪造这种效果:遍历涉及浮动视图的所有约束,并不断更新其常量属性以反映滚动视图的内容偏移。
答案 1 :(得分:0)
另一种方法是使您的滚动视图改为UICollectionView,并使浮动视图成为补充视图。然后通过实现layoutAttributesForElementsInRect:
-(NSArray *)layoutAttributesForElementsInRect:(CGRect)rect {
NSArray *layoutAttributes = [super layoutAttributesForElementsInRect:rect];
NSMutableArray *mutableAttributes = [layoutAttributes mutableCopy];
UICollectionViewLayoutAttributes *floatingViewAttributes = [UICollectionViewLayoutAttributes layoutAttributesForSupplementaryViewOfKind:@"my floating view" withIndexPath:[NSIndexPath indexPathForItem:0 inSection:0]];
CGFloat floatingViewY = (self.collectionView.frame.size.height - floatingViewHeight) + self.collectionView.contentOffset.y;
CGRect frame = CGRectMake(floatingViewX, floatingViewY, floatingViewWidth, floatingViewHeight);
floatingViewAttributes.frame = frame;
floatingViewAttributes.zIndex = someLargePostiveInteger;
[mutableAttributes addObject:floatingViewAttributes];
return mutableAttributes;
}
UICollectionView
可能不适合您的申请,但我认为我可能会将其丢弃。