为每一行的 UICollectionViewCell 设置自定义 space

Set custom space for UICollectionViewCell for every rows

我使用 UiCollectionView 构建 ViewController,并创建了自定义视图以显示在每个单元格中。 这是我的控制器上用于显示、调整单元格大小的代码。 我需要在 UiCollectionView

中的每一行有 3 个单元格
class HomeViewController: UIViewController, UICollectionViewDelegate, UICollectionViewDataSource , UICollectionViewDelegateFlowLayout{
    @IBOutlet weak var collectionView: UICollectionView!
    var listaCategorie = [CategoryModel]()
    
    
    func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
        return self.listaCategorie.count
    }
    
    func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {

         let noOfCellsInRow = 3

         let flowLayout = collectionViewLayout as! UICollectionViewFlowLayout
         let totalSpace = flowLayout.sectionInset.left
             + flowLayout.sectionInset.right
            + 30
             + (flowLayout.minimumInteritemSpacing * CGFloat(noOfCellsInRow - 1))
         let size = Int((collectionView.bounds.width - totalSpace) / CGFloat(noOfCellsInRow))
        return CGSize(width: 100, height: 130)
     }

    // UICollectionViewDelegateFlowLayout method

    func collectionView(collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout,
    insetForSectionAtIndex section: Int) -> UIEdgeInsets {
        let cellWidthPadding = collectionView.frame.size.width / 30
        let cellHeightPadding = collectionView.frame.size.height / 4
        return UIEdgeInsets(top: cellHeightPadding,left: cellWidthPadding, bottom: cellHeightPadding,right: cellWidthPadding)
    }
    
    public func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
        
        var category = self.listaCategorie[indexPath.row];
        
    }
    
    func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
        let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "cella", for: indexPath) as! CustomCellViewsCategories
         
         var puntoLuce = self.listaCategorie[indexPath.row];
         
        cell.labelCategoryName.text = puntoLuce.description
        //cell.image.image = UIImage(named: "light-bulb-2.png");
         cell.backgroundColor = getUIColorFromRGBThreeIntegers(red: 63,green: 162,blue: 217);
         cell.layer.cornerRadius = 6
         cell.layer.masksToBounds = false;
         cell.layer.shadowColor = UIColor.black.cgColor
         cell.layer.shadowOffset = CGSize(width: 0, height: 0)
         cell.layer.shadowOpacity = 0.5
       

        
        //RECUPERO LA DIMENSIONE
        let noOfCellsInRow = 4

        //FINE RECUPERO DIMENSIONE
        
        
        if(puntoLuce.imageUrl != ""){
            let imageUrl:NSURL = NSURL(string: puntoLuce.imageUrl!)!
            
            DispatchQueue.global(qos: .userInitiated).async {
                let imageData:NSData = NSData(contentsOf: imageUrl as URL)!
                DispatchQueue.main.async {
                    let image = UIImage(data: imageData as Data)
                    cell.imageCategory.image = image
                }
            }
        }
        return cell
    }
    
    func getUIColorFromRGBThreeIntegers(red: Int, green: Int, blue: Int) -> UIColor {
        return UIColor(red: CGFloat(Float(red) / 255.0),
                       green: CGFloat(Float(green) / 255.0),
                       blue: CGFloat(Float(blue) / 255.0),
                       alpha: CGFloat(1.0))
    }
    

    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view, typically from a nib.
        self.title = "ARRIVA ARRIVA"
        //on click su label temp
        let tap = UITapGestureRecognizer(target: self, action: #selector(HomeViewController.tapFunction))
        getCategoryList()
        collectionView.delegate = self // Unless you have already defined the delegate in IB
        collectionView.dataSource = self // Unless you have already defined the dataSource in IB
        self.collectionView.frame = self.collectionView.frame.inset(by: UIEdgeInsets(top: 0, left: 0, bottom: 0, right: 0))
    }
    
    @objc func tapFunction() {
           // handle label tap here
           print("click");
       }
    
    func getCategoryList(){
        var params = [
            "" : ""
        ]
        let postUrl = APIRequest(endPoint: "category_list")
        postUrl.sendRequest(parameters: params as! [String : String]) {
            responseObject, error in
            let user = CategoryModel(id: "0",
            description: "Tutti",
            imageUrl: "")
            self.listaCategorie.append(user)
            guard let responseObject = responseObject, error == nil else {
                print(error ?? "Unknown error")
                return
            }
            do{
                let messageData = try JSONDecoder().decode(ResponseCategoryModel.self, from: responseObject)
                var array = messageData.result
                for categoryModel in array {
                    let user = CategoryModel(id: "",
                                             description: categoryModel.categoryName,
                                             imageUrl: categoryModel.image)
                    self.listaCategorie.append(user)
                }
                print(array.count);
               
                DispatchQueue.main.async { // Correct
                    self.collectionView.reloadData()
                }
                
            }catch{
                print("errore durante la decodifica dei dati")
            }
    }
}

但这是结果:

正如您从照片中看到的那样,3 个单元格中也有 space。有没有办法通过cells?

设置负space

编辑 我尝试在第一次响应时使用代码。这是结果

添加 UICollectionViewDelegateFlowLayout 委托并添加这些方法并根据您的要求更新您的值,例如:-

let edge    : CGFloat = 10.0
let spacing : CGFloat = 10.0
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
    let noOfColumn = 3
    let collectionviewWidth = collectionView.frame.width
    let bothEdge =  CGFloat(edge + edge) // left + right
    let excludingEdge = collectionviewWidth - bothEdge
    let cellWidthExcludingSpaces = excludingEdge - ((noOfColumn-1) * spacing)
    let finalCellWidth = cellWidthExcludingSpaces / noOfColumn
    let height = finalCellWidth
    return CGSize(width: finalCellWidth, height: height)
}

UICollectionViewCompositionalLayout 将为您提供一个自动调整为集合视图大小的布局。删除所有与流布局相关的代码,并在 viewDidLoad:

中创建组合布局
// Cell will be the full height of the enclosing group
let cellHeight = NSCollectionLayoutDimension.fractionalHeight(1)
// Cell will be 1/3 width of the enclosing group
let cellWidth = NSCollectionLayoutDimension.fractionalWidth(0.333)
// The size of the cell
let size = NSCollectionLayoutSize(widthDimension: cellWidth, heightDimension: cellHeight)
// This item represents a single cell
let item = NSCollectionLayoutItem(layoutSize: size)
// The cell will be inset by these distances within the item
item.contentInsets = NSDirectionalEdgeInsets(top: 10, leading: 10, bottom: 10, trailing: 10)

// The group will be a fixed height
let groupHeight = NSCollectionLayoutDimension.absolute(130)
// The group will occupy the full available width
let groupWidth = NSCollectionLayoutDimension.fractionalWidth(1)
// The group will repeat to hold as many of the cells as it can in a horizontal row before wrapping
let group = NSCollectionLayoutGroup.horizontal(layoutSize: NSCollectionLayoutSize(widthDimension: groupWidth, heightDimension: groupHeight), subitems: [item])

// The actual section, which consists of a single group
let section = NSCollectionLayoutSection(group: group)
// The insets of the group from the edge of the collection view
section.contentInsets = NSDirectionalEdgeInsets(top: 10, leading: 10, bottom: 10, trailing: 10)

// Create and assign the layout
let layout = UICollectionViewCompositionalLayout(section: section)
collectionView.collectionViewLayout = layout

我试着把它分成几块,所以它很有意义,这些布局可能需要一些时间来让你的头脑清醒过来。

它为您提供以下纵向布局:

横向:

如果您想要固定的单元格大小,请使用 .absoluteWidth 作为单元格宽度,并向组中添加 interItemSpacing.flexible

使用 UICollectionViewFlowLayout 你可以用比问题中更少的代码获得非常相似的结果。对于一个普通项目,我拥有的唯一与集合视图相关的代码是 viewDidLoad():

(collectionView.collectionViewLayout as? UICollectionViewFlowLayout)?.sectionInset = .init(top: 10, left: 10, bottom: 10, right: 10)

那么这个单流布局委托方法:

func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
    var width = (collectionView.bounds.width - 20) / 3
    width -= 10
    return CGSize(width: width, height: 130)
}

这为您提供纵向或横向每行三列。