我想在联系人应用程序上调整顶视图的效果类似吗?

时间:2017-01-30 12:23:53

标签: ios uiscrollview

原生联系人应用程序具有有趣的效果 - 当用户尝试滚动时,滚动视图会使用头像推送顶视图,并且只有当顶视图处于“小模式”时才会向上滚动。

enter image description here

enter image description here

我可以通过didScroll方法调整滚动视图的大小。但问题是,内容抵消也在改变,而我推顶了。在本机联系人中,仅当顶视图处于“小模式”时,内容偏移才会更改

有任何建议,他们是怎么做到的?

2 个答案:

答案 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
    }