cellForItemAtIndexPathiOS UICollectionView如何创建具有不同大小的项目的水平滚动矩形布局?

问题描述 投票:1回答:2

iOS UICollectionView如何创建内部具有不同大小的项目的水平滚动矩形布局。

我想使用UICollectionView创建矩形布局,如下所示。我该如何实现?

  • UICollectionView

  • 水平滚动

  • 矩形布局

  • 每个项目的宽度和高度相对于屏幕大小都是固定的。

以下是320 * 480 iPhone分辨率的尺寸。下面更新了屏幕。

enter image description here

Item 1 Size is - (213*148)
Item 2 Size is - (106*75)
Item 3 Size is - (106*74)
Item 4 Size is - (106*88)
Item 5 Size is - (106*88)
Item 6 Size is - (106*88)
Item 7 Size is - (320*237)
Item 8 Size is - (320*237)
Item 9 Size is - (320*237)

例如,在第6项之后,每个项的尺寸为320 * 237

如何为上述UI设计创建自定义布局?

必须感谢您提供快速的解决方案。预先感谢。

ios swift uicollectionview uicollectionviewlayout uicollectionviewflowlayout
2个回答
1
投票

我建议在CollectionViewCell(固定尺寸)内部使用StackView来创建网格布局,如您的帖子中所示。

GridStackView下方,根据使用方法addCell(view: UIView)添加的视图数创建动态网格布局。

将此GridStackView添加为CollectionViewCell的唯一子视图,将所有边缘固定到侧面,以便完全填充CollectionViewCell。

[准备CollectionViewCell时,使用方法addCell(view: UIView)向其中添加图块视图。

如果仅添加一个视图,则它将显示单个视图,该视图占据整个GridStackView,并占据整个CollectionViewCell。如果添加了多个视图,它将自动将它们布置在CollectionViewCell内部。

您可以调整下面的代码以获得所需的布局,以计算行和列。当前的实现需要在初始化时提供rowSize,我将其用于我的一个项目,您需要对其进行一些修改以获取所需的布局。

class GridStackView: UIStackView {
    private var cells: [UIView] = []
    private var currentRow: UIStackView?
    var rowSize: Int = 3
    var defaultSpacing: CGFloat = 5

    init(rowSize: Int) {
        self.rowSize = rowSize
        super.init(frame: .zero)
        translatesAutoresizingMaskIntoConstraints = false
        axis = .vertical
        spacing = defaultSpacing
        distribution = .fillEqually
    }

    required init(coder: NSCoder) {
        super.init(coder: coder)
        translatesAutoresizingMaskIntoConstraints = false
        axis = .vertical
        spacing = defaultSpacing
        distribution = .fillEqually
    }

    private func preapreRow() -> UIStackView {
        let row = UIStackView(arrangedSubviews: [])
        row.spacing = defaultSpacing
        row.translatesAutoresizingMaskIntoConstraints = false
        row.axis = .horizontal
        row.distribution = .fillEqually
        return row
    }

    func removeAllCell() {
        for item in arrangedSubviews {
            item.removeFromSuperview()
        }
        cells.removeAll()
        currentRow = nil
    }

    func addCell(view: UIView) {
        let firstCellInRow = cells.count % rowSize == 0
        if currentRow == nil || firstCellInRow {
            currentRow = preapreRow()
            addArrangedSubview(currentRow!)
        }
        view.translatesAutoresizingMaskIntoConstraints = false
        cells.append(view)
        currentRow?.addArrangedSubview(view)
        setNeedsLayout()
    }
}

Layout with current implementation


0
投票

当我使用下面的代码时,我得到的输出如下。

import UIKit

class ViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()
        setUpCollectionView()
        // Do any additional setup after loading the view.
    }
    func setUpCollectionView() {
        self.view.backgroundColor = .white
        let layout = UICollectionViewFlowLayout()
//        layout.minimumInteritemSpacing = 1
//        layout.minimumLineSpacing = 1
        layout.scrollDirection = .horizontal
        let collectionView = CollectionView(frame: .zero, collectionViewLayout: layout)
        view.addSubview(collectionView)
        collectionView.bounces = false
        collectionView.leadingAnchor.constraint(equalTo: view.leadingAnchor).isActive = true
        collectionView.trailingAnchor.constraint(equalTo: view.trailingAnchor).isActive = true
        collectionView.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor).isActive = true
        collectionView.heightAnchor.constraint(equalToConstant: 240).isActive = true
        collectionView.translatesAutoresizingMaskIntoConstraints = false
    }

}
class CollectionView: UICollectionView {
    override init(frame: CGRect, collectionViewLayout layout: UICollectionViewLayout) {
        super.init(frame: frame, collectionViewLayout: layout)
        self.register(CollectionViewCell.self, forCellWithReuseIdentifier: CollectionViewCell.identifier)
        self.dataSource = self
        self.delegate = self
        self.isPagingEnabled = true

    }

    required init?(coder: NSCoder) {
        fatalError()
    }

}
extension CollectionView: UICollectionViewDataSource {
    func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
        return 10
    }

    func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
        let cell = collectionView.dequeueReusableCell(withReuseIdentifier: CollectionViewCell.identifier, for: indexPath) as! CollectionViewCell
        cell.backgroundColor = .blue
        cell.label.text = "\(indexPath.row)"

        let row = indexPath.row
        switch row {
        case 0:
            cell.backgroundColor = .red
        case 1:
            cell.backgroundColor = .blue
        case 2:
            cell.backgroundColor = .purple
        case 3:
            cell.backgroundColor = .orange
        case 4:
            cell.backgroundColor = .cyan
        case 5:
            cell.backgroundColor = .green
        case 6:
            cell.backgroundColor = .magenta
        case 7:
            cell.backgroundColor = .white
        case 8:
            cell.backgroundColor = .blue
        case 9:
            cell.backgroundColor = .green
        default:
            cell.backgroundColor = .systemPink
        }
        return cell
    }


}

extension  CollectionView: UICollectionViewDelegateFlowLayout {
    func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
        let row = indexPath.row
        let width = collectionView.frame.width
        let other = width / 3

        let height = collectionView.frame.height
        let o_height =  height / 3
        switch row {
        case 0:
            return CGSize(width: other * 2, height: o_height * 2)
        case 1:
            return CGSize(width: other * 2, height: o_height)
        case 2:
            return CGSize(width: other, height: o_height)
        case 3:
            return CGSize(width: other, height: o_height)
        case 4:
            return CGSize(width: other, height: o_height)
        case 5, 6, 7:
            return CGSize(width: other, height: o_height)
        default:
            return CGSize(width: width, height: height)
        }
    }

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



class CollectionViewCell: UICollectionViewCell {
    static let identifier = "CollectionViewCell"

    let label = UILabel()

    override init(frame: CGRect) {
        super.init(frame: frame)
        self.contentView.addSubview(label)
        label.centerXAnchor.constraint(equalTo: contentView.centerXAnchor).isActive = true
        label.centerYAnchor.constraint(equalTo: contentView.centerYAnchor).isActive = true
        label.translatesAutoresizingMaskIntoConstraints = false
    }

    required init?(coder: NSCoder) {
        fatalError()
    }
}

enter image description here

© www.soinside.com 2019 - 2024. All rights reserved.