0

我想使用UIKit.
在此处输入图像描述

目前我正在UICollectionView结合使用 a 和Composotional Layout. 以下代码产生此结果:
在此处输入图像描述

相关方法

private static func createCompositionalLayout() -> UICollectionViewCompositionalLayout {
    let headerItem = NSCollectionLayoutItem(
        layoutSize: NSCollectionLayoutSize(
            widthDimension: .fractionalWidth(1.0),
            heightDimension: .absolute(35)
        )
    )
    
    let horizontalGroupItem = NSCollectionLayoutItem(
        layoutSize: NSCollectionLayoutSize(
            widthDimension: .fractionalWidth(0.95),
            heightDimension: .fractionalHeight(1.0)
        )
    )
    let horizontalMainGroup = NSCollectionLayoutGroup.horizontal(
        layoutSize: NSCollectionLayoutSize(
            widthDimension: .fractionalWidth(1.0),
            heightDimension: .absolute(100)
        ),
        subitems: [horizontalGroupItem]
    )
    horizontalMainGroup.interItemSpacing = .fixed(10)
    
    let group = NSCollectionLayoutGroup.vertical(
        layoutSize: NSCollectionLayoutSize(
            widthDimension: .fractionalWidth(1.0),
            heightDimension: .absolute(135)
        ),
        subitems: [headerItem, horizontalMainGroup])
    
    let section = NSCollectionLayoutSection(group: group)
    section.interGroupSpacing = 10
    section.orthogonalScrollingBehavior = .continuous
    
    let layout = UICollectionViewCompositionalLayout(section: section)
    
    return layout
}

所以主要问题是,顶部元素没有占据该部分的整个宽度。相反,它仅限于group. 有谁知道如何得到想要的结果?:-)

完整示例

import UIKit

class ViewController: UIViewController {
    
    private let colors: [UIColor] = [.systemTeal, .systemBlue, .systemGray, .systemOrange]
    private let collectionView = UICollectionView(frame: .zero, collectionViewLayout: ViewController.createCompositionalLayout())
    
    override func viewDidLoad() {
        super.viewDidLoad()
        view.addSubview(collectionView)
        
        collectionView.backgroundColor = .systemBackground
        collectionView.frame = view.bounds
        collectionView.dataSource = self
        collectionView.register(MyCollectionViewCell.self, forCellWithReuseIdentifier: MyCollectionViewCell.reuseID)
    }
    
private static func createCompositionalLayout() -> UICollectionViewCompositionalLayout {
    let headerItem = NSCollectionLayoutItem(
        layoutSize: NSCollectionLayoutSize(
            widthDimension: .fractionalWidth(1.0),
            heightDimension: .absolute(35)
        )
    )
    
    let horizontalGroupItem = NSCollectionLayoutItem(
        layoutSize: NSCollectionLayoutSize(
            widthDimension: .fractionalWidth(0.95),
            heightDimension: .fractionalHeight(1.0)
        )
    )
    let horizontalMainGroup = NSCollectionLayoutGroup.horizontal(
        layoutSize: NSCollectionLayoutSize(
            widthDimension: .fractionalWidth(1.0),
            heightDimension: .absolute(100)
        ),
        subitems: [horizontalGroupItem]
    )
    horizontalMainGroup.interItemSpacing = .fixed(10)
    
    let group = NSCollectionLayoutGroup.vertical(
        layoutSize: NSCollectionLayoutSize(
            widthDimension: .fractionalWidth(1.0),
            heightDimension: .absolute(135)
        ),
        subitems: [headerItem, horizontalMainGroup])
    
    let section = NSCollectionLayoutSection(group: group)
    section.interGroupSpacing = 10
    section.orthogonalScrollingBehavior = .continuous
    
    let layout = UICollectionViewCompositionalLayout(section: section)
    
    return layout
}

}

extension ViewController: UICollectionViewDataSource {
    func numberOfSections(in collectionView: UICollectionView) -> Int {
        return 1
    }
    
    func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
        return 4
    }
    
    func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
        let cell = collectionView.dequeueReusableCell(withReuseIdentifier: MyCollectionViewCell.reuseID, for: indexPath) as? MyCollectionViewCell
        cell?.backgroundColor = colors[indexPath.item]
        cell?.label.text = "\(indexPath.item)"
        
        return cell ?? UICollectionViewCell()
    }
}

//MARK: - CollectionViewCell
class MyCollectionViewCell: UICollectionViewCell {
    static let reuseID = "myCell"
    
    let label = UILabel()
    
    override init(frame: CGRect) {
        super.init(frame: frame)
        contentView.addSubview(label)
        label.frame = contentView.bounds
    }
    
    required init?(coder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
}

4

1 回答 1

1

目前您将 HeaderItem 添加到组中,这就是它被限制为组宽度的原因。

您可以使用NSCollectionLayoutSection的边界补充项来实现所需的效果。

为此,您需要更新HeaderItem

 let headerItem = NSCollectionLayoutBoundarySupplementaryItem(
     layoutSize: NSCollectionLayoutSize(
         widthDimension: .fractionalWidth(1.0),
         heightDimension: .absolute(35)
     ),
     elementKind: "section-header",
     alignment: .top
  )

将其添加到布局部分:

section.boundarySupplementaryItems = [headerItem]

注册它:

collectionView.register(HeaderRV.self, forSupplementaryViewOfKind: "section-header", withReuseIdentifier: "HeaderRV")

创建 HeaderRV 类:

class HeaderRV: UICollectionReusableView {
    
    let label = UILabel()
    
    override init(frame: CGRect) {
        super.init(frame: frame)
        self.addSubview(label)
        label.frame = self.bounds
    }
    
    required init?(coder: NSCoder) { 
        fatalError("Not happening") 
    }
}

最后,您需要在 UICollectionViewDataSource 中添加collectionView (_:viewForSupplementaryElementOfKind:at :)

func collectionView(_ collectionView: UICollectionView, viewForSupplementaryElementOfKind kind: String, at indexPath: IndexPath) -> UICollectionReusableView {
    let header = collectionView.dequeueReusableSupplementaryView(ofKind: kind, withReuseIdentifier: "HeaderRV", for: indexPath) as! HeaderRV
    
    header.backgroundColor = .red
    header.label.text = "\(indexPath.item)"
    
    return header
}

完整代码:

import UIKit

class ViewController: UIViewController {
    
    private let colors: [UIColor] = [.systemTeal, .systemBlue, .systemGray, .systemOrange]
    private let collectionView = UICollectionView(frame: .zero, collectionViewLayout: ViewController.createCompositionalLayout())
    
    override func viewDidLoad() {
        super.viewDidLoad()
        view.addSubview(collectionView)
        
        collectionView.backgroundColor = .systemBackground
        collectionView.frame = CGRect(x: 5, y: 0, width: view.bounds.width - 10, height: view.bounds.height)
        collectionView.dataSource = self
        
        collectionView.register(MyCollectionViewCell.self, forCellWithReuseIdentifier: MyCollectionViewCell.reuseID)
        collectionView.register(HeaderRV.self, forSupplementaryViewOfKind: "section-header", withReuseIdentifier: "HeaderRV")
    }
    
    private static func createCompositionalLayout() -> UICollectionViewCompositionalLayout {
        let headerItem = NSCollectionLayoutBoundarySupplementaryItem(
            layoutSize: NSCollectionLayoutSize(
                widthDimension: .fractionalWidth(1.0),
                heightDimension: .absolute(50)
            ),
            elementKind: "section-header",
            alignment: .top
        )
        headerItem.contentInsets.bottom = 5
                
        let horizontalGroupItem = NSCollectionLayoutItem(
            layoutSize: NSCollectionLayoutSize(
                widthDimension: .fractionalWidth(1.0),
                heightDimension: .fractionalHeight(1.0)
            )
        )
                
        let group = NSCollectionLayoutGroup.horizontal(
            layoutSize: NSCollectionLayoutSize(
                widthDimension: .fractionalWidth(0.65),
                heightDimension: .absolute(135)
            ),
            subitems: [horizontalGroupItem])
                
        let section = NSCollectionLayoutSection(group: group)
        section.interGroupSpacing = 50
        section.boundarySupplementaryItems = [headerItem]
        section.orthogonalScrollingBehavior = .continuous
        
        let layout = UICollectionViewCompositionalLayout(section: section)
        
        return layout
    }
    
}

extension ViewController: UICollectionViewDataSource {
    func numberOfSections(in collectionView: UICollectionView) -> Int {
        return 1
    }
    
    func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
        return 4
    }
    
    func collectionView(_ collectionView: UICollectionView, viewForSupplementaryElementOfKind kind: String, at indexPath: IndexPath) -> UICollectionReusableView {
        let header = collectionView.dequeueReusableSupplementaryView(ofKind: kind, withReuseIdentifier: "HeaderRV", for: indexPath) as! HeaderRV
        
        header.backgroundColor = .red
        header.label.text = "\(indexPath.item)"
        
        return header
    }
    
    func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
        let cell = collectionView.dequeueReusableCell(withReuseIdentifier: MyCollectionViewCell.reuseID, for: indexPath) as? MyCollectionViewCell
        cell?.backgroundColor = colors[indexPath.item]
        cell?.label.text = "\(indexPath.item)"
        
        return cell ?? UICollectionViewCell()
    }
}

//MARK: - CollectionViewCell
class MyCollectionViewCell: UICollectionViewCell {
    static let reuseID = "myCell"
    
    let label = UILabel()
    
    override init(frame: CGRect) {
        super.init(frame: frame)
        contentView.addSubview(label)
        label.frame = contentView.bounds
    }
    
    required init?(coder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
}

//MARK: - CollectionReusableView
class HeaderRV: UICollectionReusableView {
    
    let label = UILabel()
    
    override init(frame: CGRect) {
        super.init(frame: frame)
        self.addSubview(label)
        label.frame = CGRect(x: 0, y: 0, width: frame.width, height: frame.height - 5)
    }
    
    required init?(coder: NSCoder) { fatalError("Not happening") }
}
于 2021-08-06T17:18:49.700 回答