设置collectionView大小。(sizeForItemAtIndexPath函数无法工作)Swift 3

68

我有一个tableView,每个tableViewCell中都有一个collectionView

我尝试使用以下代码更改collectionView的大小:


 func collectionView(_ collectionView: UICollectionView,
                    layout collectionViewLayout: UICollectionViewLayout,
                    sizeForItemAt indexPath: IndexPath) -> CGSize {

    if collectionView.tag == 2{

        return CGSize(width: 100, height: 100)

    }else if collectionView.tag == 4 {


        return CGSize(width: 222, height: 200)

    }else{


        return CGSize(width: 10, height: 10)
    }

}

问题在于没有错误,但单元格大小不会改变。

如果您需要了解更多信息,请撰写评论。

谢谢。


你的第一条语句说你有一个 tableView,但这看起来像是一个 collectionView。你两个都有吗,还是只有一个? - brandonscript
@brandonscript 在表格视图单元内部有一个集合视图。 - 0ndre_
7个回答

297
首先,别忘了从 UICollectionViewDelegateFlowLayout 委托进行继承。
对于单个集合视图显示逻辑:
 func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
    let width = ((collectionView.frame.width - 15) / 2) // 15 because of paddings
    print("cell width : \(width)")
    return CGSize(width: width, height: 200)
}

在Storyboard中一个重要的点是不要忘记将Estimate Size设置为None

estimate_size_none


26
哇,你救了我的一天。在将“Estimate Size”从自动更改为“None” (+将单元格的最小间距从10更改为0,将线条的最小间距从10更改为0)之后,func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) 起作用了! 在进行编辑之前,我遇到了意外的单元格宽度和最小的单元格间距。 - mazend
1
是的,@mazend和我遇到了同样的问题。经过很长时间,我偶然发现了解决方法。我很高兴能够帮助你。 - Burak Dizlek
4
我正在使用XCode 11.2.1版本,该版本的“预估大小”默认为“自动”。所以将其改为“无”对我很有帮助。谢谢! - Rameez
1
感谢估算尺寸点...我浪费了半天的时间调试我的项目尺寸。 - Happiehappie
如果您在collectionView中使用了xib,那么这也是必要的。 - Robert J. Clegg
显示剩余6条评论

63

这个方法的签名已经在Swift 3中更改为:

func collectionView(_ collectionView: UICollectionView,
                    layout collectionViewLayout: UICollectionViewLayout,
                    sizeForItemAt indexPath: IndexPath) -> CGSize {
    // your code here
}

注意微妙的区别:(_ collectionView: ... 而不是 (collectionView: ...

这是因为在 Swift 3 中,您必须明确指定第一个参数的标签。您可以通过添加下划线字符_来覆盖此默认行为。

此外,请确保您的类同时采用了UICollectionViewDelegateUICollectionViewDelegateFlowLayout 协议。

class MyViewController: UICollectionViewDelegateFlowLayout, UICollectionViewDelegate {

    // your code here

    func collectionView(_ collectionView: UICollectionView,
                layout collectionViewLayout: UICollectionViewLayout,
                sizeForItemAt indexPath: IndexPath) -> CGSize {
        // your code here
    }
}

请参考此链接了解Swift 3的变更。


我已经更新了我的代码,但它并没有改变单元格的大小:/ - 0ndre_
23
在代理方法调用中添加 "UICollectionViewDelegateFlowLayout"。 - Baljeet Singh
4
这是正确的答案。非常感谢你!UICollectionViewDelegateFlowLayout 是关键。 - RanLearns
@BaljeetSingh 你说的“在代理调用中添加'UICollectionViewDelegateFlowLayout'”是什么意思? - nambatee
1
@nambatee let layout: UICollectionViewFlowLayout = UICollectionViewFlowLayout() layout.sectionInset = UIEdgeInsets(top: -1, left: -1, bottom: -1, right: -1) let value:CGFloat = (UIScreen.main.bounds.width)/2; layout.itemSize = CGSize(width: value, height: value) layout.minimumInteritemSpacing = 0 layout.minimumLineSpacing = 0 GridView!.collectionViewLayout = layout - Baljeet Singh
对我来说,这是UICollectionViewDelegateFlowLayout,之前的开发人员没有添加它。 - Ramesh Sanghar

23

您需要在类声明中指定实现协议UICollectionViewDelegateFlowLayout。

class PhrasesCompactCollectionViewController: UICollectionViewController, UICollectionViewDelegateFlowLayout

5

这是我的代码,目前它可以正常运行:

        collectionView.delegate = dataSourceDelegate
        collectionView.dataSource = dataSourceDelegate
        collectionView.tag = row
        collectionView.setContentOffset(collectionView.contentOffset, animated:false)
        collectionView.reloadData()
        collectionView.register(UINib(nibName: "eventsCollectionViewCell", bundle: nil), forCellWithReuseIdentifier: "eventsCollectionViewCell")


        if row == 2{


            let layout: UICollectionViewFlowLayout = UICollectionViewFlowLayout()
            layout.sectionInset = UIEdgeInsets(top: 0, left: 0, bottom: 0, right: 0)
            layout.itemSize = CGSize(width: 120, height: 120)
            layout.scrollDirection = .horizontal

            collectionView.collectionViewLayout = layout

        }else if row == 4 {


            let layout: UICollectionViewFlowLayout = UICollectionViewFlowLayout()
            layout.sectionInset = UIEdgeInsets(top: 0, left: 0, bottom: 0, right: 0)
            layout.itemSize = CGSize(width: 222, height: 200)
            layout.scrollDirection = .horizontal

            collectionView.collectionViewLayout = layout

        }else{

            print("else")
        }

5
"行"是什么?它是如何声明和赋值的? - Md Rais

3
尝试添加 标签。
collectionView.delegate = dataSource

较长版:

对我来说,这只是一个小错误 -

collectionView.dataSource = self

这将调用这些方法。
func numberOfSections(in collectionView: UICollectionView) -> Int
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell

然而,它不会进行调用。
func collectionView(_ collectionView: UICollectionView,
                    layout collectionViewLayout: UICollectionViewLayout,
                    sizeForItemAt indexPath: IndexPath) -> CGSize

因为这不是UICollectionView的数据源(dataSource)的一部分,而是UICollectionView的委托(delegate)的一部分。因此加入以下内容可以解决我的问题。
collectionView.delegate = dataSource

2
为什么您要将collectionView.delegate设置为dataSource而不是collectionView.delegate = self? - Umair Afzal

0
我曾经也遇到了同样的问题!如果你让尺寸缩小一半(width/2),那么它仍然会看起来像整个宽度,因为内填充被添加到了 width/2。
修复方法:确保在 Storyboard 中将节边距设置为 0。或者将 width/2 调整为包括节边距的尺寸。
我花了一些时间来解决这个问题;-)

-1
不要忘记将UICollectionViewFlowLayout对象分配给你的collectionViewLayout,因为默认情况下UICollectionView使用UICollectionViewLayout(而不是UICollectionViewFlowLayout)。

let flowLayout = UICollectionViewFlowLayout()

collectionView.collectionViewLayout = flowLayout


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