原生联系人应用程序具有有趣的效果 - 当用户尝试滚动时,滚动视图会使用头像推送顶视图,并且只有当顶视图处于“小模式”时才会向上滚动。
我可以通过didScroll
方法调整滚动视图的大小。但问题是,内容抵消也在改变,而我推顶了。在本机联系人中,仅当顶视图处于“小模式”时,内容偏移才会更改
有任何建议,他们是怎么做到的?
答案 0 :(得分:4)
这是一个如何做到的示例项目:
https://github.com/lukaswuerzburger/resizeable-tableview-header
您只需拥有一个视图控制器,其中包含一个表视图和一个自定义视图(可调整大小的标题)。在scrollViewDidScroll
上更改高度约束。
PS:主视图和详细视图控制器之间的过渡并不完美,但也许有人可以帮助我。当弹出回主视图控制器时,navigationBar
的{{1}}和backgroundImage
的更改实际上不起作用。
答案 1 :(得分:1)
赏金的答案很好,但它仍然为这个问题提供了一些不稳定的解决方案。如果你想要像本地人一样,这是你的解决方案。我最近一直在玩集合视图,并获得了更多的经验。我发现的一件事是使用自定义布局可以轻松解决这个问题:
class CustomCollectionViewFlowLayout: UICollectionViewFlowLayout {
let minHeightForHeader: CGFloat = 50
let offsetFromTop: CGFloat = 20
override func layoutAttributesForSupplementaryView(ofKind elementKind: String, at indexPath: IndexPath) -> UICollectionViewLayoutAttributes? {
// get current attributes
let attributes = super.layoutAttributesForSupplementaryView(ofKind: elementKind, at: indexPath)
// get first section
if let attributes = attributes, elementKind == UICollectionElementKindSectionHeader && indexPath.section == 0 {
if let collectionView = collectionView {
// now check for content offset
var frame = attributes.frame
let yOffset = collectionView.contentOffset.y
if yOffset >= -offsetFromTop {
let calculatedHeight = frame.size.height - (yOffset + offsetFromTop)
let maxValue = minHeightForHeader > calculatedHeight ? minHeightForHeader : calculatedHeight
frame.size.height = maxValue
attributes.frame = frame
}
else {
frame.origin.y = offsetFromTop + yOffset
attributes.frame = frame
}
}
return attributes
}
// default return
return attributes
}
override func shouldInvalidateLayout(forBoundsChange newBounds: CGRect) -> Bool {
return true
}
}
只需使用此自定义类替换默认布局,并在设置方法中的某处添加此行
flowLayout.sectionHeadersPinToVisibleBounds = true
瞧!
编辑:还有一个可选的裁剪部分方法,当你滚动到某个部分时,滚动可能会继续或返回:
override func targetContentOffset(forProposedContentOffset proposedContentOffset: CGPoint, withScrollingVelocity velocity: CGPoint) -> CGPoint {
if let collectionView = collectionView {
let yOffset = collectionView.contentOffset.y
if yOffset + offsetFromTop >= maxHeightForHeader / 2 && yOffset + offsetFromTop < maxHeightForHeader && !(velocity.y < 0) || velocity.y > 0{
return CGPoint.init(x: 0, y: maxHeightForHeader - minHeightForHeader - offsetFromTop)
}
if yOffset + offsetFromTop < maxHeightForHeader / 2 && yOffset + offsetFromTop > 0 || velocity.y < 0 {
return CGPoint.init(x: 0, y: -offsetFromTop)
}
}
return proposedContentOffset
}