【问题标题】:Unexpected UICollectionView layout inside UITableViewCellUITableViewCell 内出现意外的 UICollectionView 布局
【发布时间】:2021-07-12 21:35:37
【问题描述】:

我有一个表格单元格,它由 UICollectionView + 一些其他项目组成:

import UIKit

class PhotosTableViewCell: UITableViewCell {
    var navigationHandler : PhotoNavigationHandler?

    private let photoWidth = (UIScreen.main.bounds.width)/4
    
    private let titleLabelView : UILabel = {
        let view = UILabel()
        view.font = UIFont.systemFont(ofSize: 24, weight: .bold)
        view.textColor = .black
        view.text = "Photos"
        view.translatesAutoresizingMaskIntoConstraints = false
        return view
    }()
    
    private lazy var buttonView : UIButton = {
        let view = UIButton()
        view.setBackgroundImage(UIImage(systemName: "arrow.right"), for: .normal)
        view.translatesAutoresizingMaskIntoConstraints = false
        view.addTarget(self, action: #selector(goToGaleryClickedHandler), for: .touchUpInside)
        return view
    }()
    
    @objc private func goToGaleryClickedHandler() {
        guard let handler = navigationHandler else {
            return
        }
        
        handler()
    }
    
    private lazy var photosPreview : UICollectionView = {
        let layout = UICollectionViewFlowLayout()
        
        let view = UICollectionView(frame: .zero, collectionViewLayout: layout)
        view.register(PhotoGaleryShortCollectionViewCell.self,
                      forCellWithReuseIdentifier: String(describing: PhotoGaleryShortCollectionViewCell.self))
        view.dataSource = self
        view.delegate = self
        view.backgroundColor = .green
        view.translatesAutoresizingMaskIntoConstraints = false
        return view
    }()
        
    override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
        super.init(style: style, reuseIdentifier: reuseIdentifier)
        setupViews()
    }
    
    required init?(coder: NSCoder) {
        super.init(coder: coder)
        setupViews()
    }

    private func setupViews()
    {
        contentView.addSubview(titleLabelView)
        contentView.addSubview(buttonView)
        contentView.addSubview(photosPreview)
        
        let constraints = [
            titleLabelView.topAnchor.constraint(equalTo: contentView.topAnchor, constant: 12),
            titleLabelView.leadingAnchor.constraint(equalTo: contentView.leadingAnchor, constant: 12),
            buttonView.centerYAnchor.constraint(equalTo: titleLabelView.centerYAnchor),
            buttonView.trailingAnchor.constraint(equalTo : contentView.trailingAnchor, constant: -12),
            buttonView.heightAnchor.constraint(equalToConstant: 30),
            buttonView.widthAnchor.constraint(equalToConstant: 30),
            photosPreview.leadingAnchor.constraint(equalTo: titleLabelView.leadingAnchor),
            photosPreview.topAnchor.constraint(equalTo : titleLabelView.bottomAnchor, constant: 12),
            photosPreview.heightAnchor.constraint(equalToConstant : photoWidth),
            photosPreview.trailingAnchor.constraint(equalTo : contentView.trailingAnchor, constant: -12),
            photosPreview.bottomAnchor.constraint(equalTo: contentView.bottomAnchor, constant: -12)
        ]
        
        NSLayoutConstraint.activate(constraints)
    }

}


extension PhotosTableViewCell : UICollectionViewDataSource {
    
    func numberOfSections(in collectionView: UICollectionView) -> Int {
        return 1
    }
    
    func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
        return 2
    }
    
    func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
        let cell =
            photosPreview.dequeueReusableCell(withReuseIdentifier:
                                                String(describing: PhotoGaleryShortCollectionViewCell.self),
                                              for: indexPath) as! PhotoGaleryShortCollectionViewCell
        return cell
    }
}

extension PhotosTableViewCell: UICollectionViewDelegateFlowLayout {
    
    func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
        return CGSize(width: photoWidth, height: photoWidth)
    }
    
    func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumLineSpacingForSectionAt section: Int) -> CGFloat {
        return 0
    }
    
    func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumInteritemSpacingForSectionAt section: Int) -> CGFloat {
        return 0
    }
    
    func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, insetForSectionAt section: Int) -> UIEdgeInsets {
        return UIEdgeInsets(top: 0, left: 0, bottom: 0, right: 0)
    }    
}

这是一个集合视图单元的实现:

import UIKit

class PhotoGaleryShortCollectionViewCell: UICollectionViewCell {
    private let area : UIView = {
        let view = UIView()
        view.backgroundColor = .blue
        view.translatesAutoresizingMaskIntoConstraints = false
        return view
    }()
    
    override init(frame: CGRect) {
        super.init(frame: frame)
        setupViews()
    }
    
    required init?(coder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
    
    func setupViews() {
        contentView.addSubview(area)
        
        let constraints = [
            area.topAnchor.constraint(equalTo: contentView.topAnchor),
            area.leadingAnchor.constraint(equalTo: contentView.leadingAnchor),
            area.trailingAnchor.constraint(equalTo: contentView.trailingAnchor),
            area.bottomAnchor.constraint(equalTo: contentView.bottomAnchor)
        ]
        
        NSLayoutConstraint.activate(constraints)
    }
}

据我了解,我应该在集合视图区域内并排放置 2 个方块。

但我得到

这里做错了什么?

【问题讨论】:

  • 主视图宽度可以设置为100%,内4格宽度分别设置为25%,忽略使用约束。

标签: swift uicollectionviewcell


【解决方案1】:

您遇到此问题是因为您正在设置单元格大小,请尝试删除这部分代码,它将得到解决

func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
    return CGSize(width: photoWidth, height: photoWidth)
}

也替换这一行

photosPreview.heightAnchor.constraint(equalToConstant : photoWidth),

用这个:

        photosPreview.heightAnchor.constraint(equalToConstant : contentView.frame.height),

【讨论】:

  • 非常感谢 - 它确实有效......但我如何设置集合视图所需的单元格大小?
  • 为什么单元格大小设置会破坏这里的布局?
  • 问题在于你实现整个事情的方式,它总是2个正方形吗?还是更多?
  • 是的,2 个方块..但它们只是占位符,它可以是任何 ui 项目
  • 你在“整个事情”下是什么意思?您能否指出我错在哪里以及实现这一点的正确方法是什么?
【解决方案2】:

您还可以在应用之前设置布局layout 并在那里设置您的大小,这里是一些示例代码:

    lazy var layout: UICollectionViewFlowLayout = {
    let layout: UICollectionViewFlowLayout = UICollectionViewFlowLayout()
    layout.itemSize = CGSize(width: photoWidth, height: photoWidth)
    layout.sectionInset = UIEdgeInsets(top: 0, left: 0, bottom: 0, right: 0)
    layout.minimumInteritemSpacing = 0
    layout.minimumLineSpacing = 0
    return layout
}()

【讨论】:

    【解决方案3】:

    要修复布局,我必须在此处添加以下行:

    layout.scrollDirection = .horizontal
    

    虽然它看起来像一个肮脏的黑客,但它确实有效。如果有人能解释一下……

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-04-02
      • 1970-01-01
      • 1970-01-01
      • 2018-09-30
      相关资源
      最近更新 更多