使用自定义布局时,sizeForItemAt方法不调用

时间:2017-08-08 20:53:03

标签: ios swift uicollectionview uikit

我正在为我的集合视图使用自定义布局,但如果我使用自定义布局 app: '?^^homeComponent' 方法则不会调用。

我的自定义布局:

sizeForItemAt

我正在public class HorizontalCollectionViewLayout : UICollectionViewLayout { var itemSize = CGSize(width: 0, height: 0) { didSet { invalidateLayout() } } private var cellCount = 0 private var boundsSize = CGSize(width: 0, height: 0) public override func prepare() { cellCount = self.collectionView!.numberOfItems(inSection: 0) boundsSize = self.collectionView!.bounds.size } public override var collectionViewContentSize: CGSize { let verticalItemsCount = Int(floor(boundsSize.height / itemSize.height)) let horizontalItemsCount = Int(floor(boundsSize.width / itemSize.width)) let itemsPerPage = verticalItemsCount * horizontalItemsCount let numberOfItems = cellCount let numberOfPages = Int(ceil(Double(numberOfItems) / Double(itemsPerPage))) var size = boundsSize size.width = CGFloat(numberOfPages) * boundsSize.width return size } public override func layoutAttributesForElements(in rect: CGRect) -> [UICollectionViewLayoutAttributes]? { var allAttributes = [UICollectionViewLayoutAttributes]() if cellCount > 0 { for i in 0...(cellCount-1) { let indexPath = IndexPath(row: i, section: 0) let attr = self.computeLayoutAttributesForCellAt(indexPath: indexPath) allAttributes.append(attr) } } return allAttributes } public override func layoutAttributesForItem(at indexPath: IndexPath) -> UICollectionViewLayoutAttributes? { return computeLayoutAttributesForCellAt(indexPath: indexPath) } public override func shouldInvalidateLayout(forBoundsChange newBounds: CGRect) -> Bool { return true } private func computeLayoutAttributesForCellAt(indexPath:IndexPath) -> UICollectionViewLayoutAttributes { let row = indexPath.row let bounds = self.collectionView!.bounds let verticalItemsCount = Int(floor(boundsSize.height / itemSize.height)) let horizontalItemsCount = Int(floor(boundsSize.width / itemSize.width)) let itemsPerPage = verticalItemsCount * horizontalItemsCount let columnPosition = row % horizontalItemsCount let rowPosition = (row/horizontalItemsCount)%verticalItemsCount let itemPage = Int(floor(Double(row)/Double(itemsPerPage))) let attr = UICollectionViewLayoutAttributes(forCellWith: indexPath) var frame = CGRect(x: 0,y: 0,width: 0,height: 0) frame.origin.x = CGFloat(itemPage) * bounds.size.width + CGFloat(columnPosition) * itemSize.width frame.origin.y = CGFloat(rowPosition) * itemSize.height frame.size = itemSize attr.frame = frame return attr } } 方法设置此布局:

viewDidLoad

其他集合视图方法工作正常,如let itemWidth = 100 let itemHeight = 100 let horizontalCV = HorizontalCollectionViewLayout(); horizontalCV.itemSize = CGSize(width: itemWidth, height: itemHeight) instagramCollection.collectionViewLayout = horizontalCV self.instagramCollection.delegate=self self.instagramCollection.dataSource=self numberOfItemsInSection等。但我无法为集合视图设置插入或单元格间距。

我尝试了以下代码,以下方法未调用。

cellForItemAt

此外,我尝试设置instets和故事板的间距也没有用。

我的集合视图现在对所有插入和间距使用零。

如何解决这个问题?

4 个答案:

答案 0 :(得分:0)

您应该添加布局委托的控制器实现。 (你添加了这些方法,但没有调用它们)

因此,不仅UICollectionViewDelegateUICollectionViewDataSource,还有UICollectionViewDelegateFlowLayout

例如,像扩展名一样。

extension YourController: UICollectionViewDelegateFlowLayout {
func collectionView(_ collectionView: UICollectionView,
                    layout collectionViewLayout: UICollectionViewLayout,
                    sizeForItemAt indexPath: IndexPath) -> CGSize {
    return CGSize.init(width: (instagramCollection.frame.width / 3.0), height: instagramCollection.frame.height / 2.0)
}

func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, insetForSectionAt section: Int) -> UIEdgeInsets {
    return UIEdgeInsets(top: 10, left: 10, bottom: 10, right: 10)
}

func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumInteritemSpacingForSectionAt section: Int) -> CGFloat {
    return 10.0
}

func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumLineSpacingForSectionAt section: Int) -> CGFloat {
    return 10.0
}

答案 1 :(得分:0)

由于您的buildscript { ext.kotlin_version = '1.3.20' repositories { google() jcenter() } dependencies { classpath 'com.android.tools.build:gradle:3.3.0' classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" } } allprojects { repositories { google() jcenter() mavenLocal() } } task clean(type: Delete) { delete rootProject.buildDir } HorizontalCollectionViewLayout的子类,因此这些函数将不会被调用,因为它们与UICollectionViewLayout无关

请注意,您正在控制器内部实现的协议为UICollectionViewLayout。该协议扩展了UICollectionViewDelegateFlowLayout协议。

因此,如果您希望调用这些函数,只需将继承的类更改为UICollectionViewDelegate

UICollectionViewFlowLayout

答案 2 :(得分:0)

当您使用自己的流程布局时,它不会被调用,因为解决方法如下:

1-定义自己的协议

protocol MyCustomCollectionLayoutDelegate: AnyObject {
    func collectionView(_ collectionView: UICollectionView, sizeForItem indexPath: IndexPath) -> CGSize
}

2-在自定义布局内添加委托属性

final class HorizontalCollectionViewLayout: UICollectionViewFlowLayout {


     weak var delegate: MyCustomCollectionLayoutDelegate?
     ....
}

3-将此协议实施到您的UICollectionViewController

class MyViewController: UICollectionViewController, MyCustomCollectionLayoutDelegate {

    var customLayout: HorizontalCollectionViewLayout? {
        let layout = collectionView?.collectionViewLayout as? DeviceDetailsCollectionLayout
        layout?.delegate = self
        return layout
    }

    func collectionView(_ collectionView: UICollectionView, sizeForItem indexPath: IndexPath) -> CGSize {
        return CGSize(width: 50, height: 60)
    }

}

4-在自定义布局类中调用您的委托方法

   public override func layoutAttributesForElements(in rect: CGRect) -> [UICollectionViewLayoutAttributes]? {

     let cellIndexPath = IndexPath(item: 0, section: 0)
     let customSize = delegate?.collectionView(collectionView, sizeForItem: cellIndexPath)

     // use your size ...

}

答案 3 :(得分:0)

如果有人犯了与我相同的错误,我将发布此消息。我在方法签名中有private关键字,请确保避免这种情况,否则sizeForItemAt将不会为您的collectionView运行