如何为UICollectionView创建一个“粘性”底部?

8
什么是为`UICollectionView`提供一个页脚并"粘着"在页面底部的最佳方法?假设`UICollectionView`全屏且只有一个区块。
目前我是通过在`collectionView:viewForSupplementaryElementOfKind:atIndexPath:`中提供一个`UICollectionReusableView`对象来实现的,但是(不出所料),当我的集合内容超出屏幕边界时,页脚就会被推出屏幕之外。
我猜关键是使用装饰视图,但我找不到任何好的代码(非IB)示例,而且苹果的文档在我看来在这个特定主题上不清楚。
关于装饰视图的更新
在构建并尝试使用装饰视图( 参考此教程)后,我遇到了一些限制-主要是在装饰视图对象和您的 UICollectionViewController 控制器对象之间没有真正的回调(装饰视图由一个 UICollectionViewLayout 对象管理,而不是 UICollectionViewController 对象)。显然,苹果公司非常关注装饰视图仅限于视觉装饰而不是数据驱动(尽管您可以通过一些方式进行修改)。

因此,“正确”的解决方案仍然让我困惑,但同时我只创建了一个静态的 UIView 对象,并且只在我的UICollectionViewController 对象中对其进行管理。它效果还行,但感觉不太对。

关于顶部固定标题更新

在过去几个月中,我在各种项目中处理类似的问题,并最近找到了一种解决方法,以实现顶部固定标题。我认为相同的方法也适用于页脚,但我还没有测试过。

有关标题的详细信息请参阅此处:

如何使补充视图在UICollectionView中像UITableView普通样式中的区段标头一样浮动

实现相当复杂,但在大多数情况下似乎运行良好。

如果这个问题没有更多的活动,我将把它关闭并指向上面的文章。

3个回答

17
基本上,您需要提供一个自定义的UICollectionViewLayout子类,当边界改变时(视图滚动时边界会改变)使其失效。 然后为补充视图提供UICollectionViewLayoutAttributes,其中中心位置更新为贴合集合视图的当前边界(顶部、底部、左侧、右侧等)。
我在github上添加了一个示例项目,演示了这种策略。
更新:从iOS 9开始,UICollectionViewFlowLayout有两个非常方便的属性,大大简化了此任务。请参见sectionHeadersPinToVisibleBoundssectionFootersPinToVisibleBounds

1
@pxlshpr 这不应该是这样的,这太低效了。 - TheCodingArt
2
无论效率如何,当边界改变时使布局失效正是苹果似乎实现iOS 9固定功能的方式。当启用固定功能并滚动时,每秒钟会多次调用“invalidateLayout”。 - jscs

0

好的..所以我尝试更新下面链接中的代码。它可以正常工作。 https://teamtreehouse.com/community/add-sticky-footer-to-uicollectionview-in-swift

class StickyFooter : UICollectionViewFlowLayout {

var footerIsFound             : Bool = false
var UICollectionAttributes    : [UICollectionViewLayoutAttributes]?


override func shouldInvalidateLayout(forBoundsChange newBounds: CGRect) -> Bool {
    return true
}


override func layoutAttributesForElements(in rect: CGRect) -> [UICollectionViewLayoutAttributes]?
{
    UICollectionAttributes = super.layoutAttributesForElements(in: rect)

    for  attributes in UICollectionAttributes! {

        if let type = attributes.representedElementKind {

            if type == UICollectionElementKindSectionFooter
            {
                footerIsFound = true
                updateFooter(attributes: attributes)
            }
        }
    }

    if (!self.footerIsFound) {

        let newItem = self.layoutAttributesForSupplementaryView(ofKind: UICollectionElementKindSectionFooter, at : NSIndexPath(row: self.UICollectionAttributes!.count, section: 0) as IndexPath)


        UICollectionAttributes?.append(newItem!)

    }

    return UICollectionAttributes
}

override func layoutAttributesForSupplementaryView(ofKind elementKind: String, at indexPath: IndexPath) -> UICollectionViewLayoutAttributes?
{
    let attributes = UICollectionViewLayoutAttributes(forSupplementaryViewOfKind: elementKind, with: indexPath)

    attributes.size = CGSize(width: self.collectionView!.bounds.size.width, height: 75)

    if elementKind.isEqualToString(find: UICollectionElementKindSectionFooter)
    {
        updateFooter(attributes: attributes)
    }
    return attributes
}


func updateFooter(attributes : UICollectionViewLayoutAttributes){
    let currentBounds = self.collectionView?.bounds
    attributes.zIndex = 1024
    attributes.isHidden = false
    let yOffset = currentBounds!.origin.y + currentBounds!.size.height - attributes.size.height/2.0
    attributes.center = CGPoint(x: currentBounds!.midX, y: yOffset)

}}

将类名“StickyFooter”分配给您的CollectionViewFlow布局。 - pankti patel

-6

UICollectionViewController(类似于UITableVC)是一种“快捷方式”,这两个类只是覆盖UIViewController,为您创建collectionView。

您可以轻松地自己完成并添加您的粘性视图。


在过去的几个月里,我通过各种项目学到了更多相关知识(自发表该问题以来),而且在我看来,这远非易事。我会更新原来的问题以供日后搜索使用,但如果您知道实现上述目标的简便方法,请详细说明。 - toblerpwn

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接