gpt4 book ai didi

ios - UICollectionViewCell 中的 UICollectionView 以编程方式

转载 作者:行者123 更新时间:2023-11-28 06:06:28 33 4
gpt4 key购买 nike

您好,我正在尝试使用 UICollectionView 创建一个像 facebook 这样的主页提要,但是我想在每个单元格中放置另一个具有 3 个单元格的 collectionView。

you can clone the project here

我有两个错误,第一个是当我在内部 Collection View 上滚动时,反弹不会将单元格带回中心。当我创建 Collection View 时,我启用了分页并将 minimumLineSpacing 设置为 0我不明白为什么会这样。当我尝试调试时,我注意到当我删除这一行时这个错误停止了

layout.estimatedItemSize = CGSize(width: cv.frame.width, height: 1)

但是删除那行给我带来了这个错误

The behavior of the UICollectionViewFlowLayout is not defined because: the item height must be less than the height of the UICollectionView minus the section insets top and bottom values, minus the content insets top and bottom values

因为我的单元格有动态高度这是一个例子

example

我的第二个问题是每个内部单元格上的文本都显示了好的文本我必须滚动到内部 Collection View 的最后一个单元格才能看到这里显示的好的文本是一个例子 example

最佳答案

您的第一个问题将通过为 OuterCell 中的 innerCollectionView 设置 minimumInteritemSpacing 来解决。所以 innerCollectionView 的定义变成了这样:

let innerCollectionView : UICollectionView = {
let layout = UICollectionViewFlowLayout()
layout.scrollDirection = .horizontal
layout.minimumLineSpacing = 0
layout.minimumInteritemSpacing = 0

let cv = UICollectionView(frame :.zero , collectionViewLayout: layout)
cv.translatesAutoresizingMaskIntoConstraints = false
cv.backgroundColor = .orange
layout.estimatedItemSize = CGSize(width: cv.frame.width, height: 1)
cv.isPagingEnabled = true
cv.showsHorizontalScrollIndicator = false

return cv

}()

第二个问题通过在 OuterCell 的 post 属性的 didSet 中添加对 reloadData 和 layoutIfNeeded 的调用来解决,如下所示:

var post: Post? {
didSet {
if let numLikes = post?.numLikes {
likesLabel.text = "\(numLikes) Likes"
}

if let numComments = post?.numComments {
commentsLabel.text = "\(numComments) Comments"
}
innerCollectionView.reloadData()
self.layoutIfNeeded()
}
}

您所看到的与单元重用有关。如果您滚动到第一个项目上的黄色边框文本然后向下滚动,您可以看到它的效果。您会看到其他人也在黄色边框文本上(尽管至少现在文本是正确的)。

编辑

作为奖励,这里提供了一种记住细胞状态的方法。

首先您需要跟踪位置何时发生变化,因此在 OuterCell.swft 中添加如下新协议(protocol):

protocol OuterCellProtocol: class {
func changed(toPosition position: Int, cell: OutterCell)
}

然后为该协议(protocol)的委托(delegate)添加一个实例变量到 OuterCell 类,如下所示:

public weak var delegate: OuterCellProtocol?

然后最后您需要添加以下方法,该方法在滚动完成时调用,计算新位置并调用委托(delegate)方法让它知道。像这样:

func scrollViewDidEndDecelerating(_ scrollView: UIScrollView) {
if let index = self.innerCollectionView.indexPathForItem(at: CGPoint(x: self.innerCollectionView.contentOffset.x + 1, y: self.innerCollectionView.contentOffset.y + 1)) {
self.delegate?.changed(toPosition: index.row, cell: self)
}
}

这就是每个单元格检测 Collection View 单元格何时更改并通知委托(delegate)人的情况。让我们看看如何使用这些信息。

OutterCellCollectionViewController 需要跟踪每个单元格在其 Collection View 中的位置,并在它们可见时更新它们。

因此,首先使 OutterCellCollectionViewController 符合 OuterCellProtocol,以便在其中一个

class OutterCellCollectionViewController: UICollectionViewController, UICollectionViewDelegateFlowLayout, OuterCellProtocol   {

然后添加一个类实例变量来将单元格位置记录到 OuterCellCollectionViewController 中,如下所示:

var positionForCell: [Int: Int] = [:]

然后添加所需的 OuterCellProtocol 方法来记录单元格位置的变化,如下所示:

func changed(toPosition position: Int, cell: OutterCell) {
if let index = self.collectionView?.indexPath(for: cell) {
self.positionForCell[index.row] = position
}
}

最后更新 cellForItemAt 方法来设置单元格的委托(delegate)并使用新的单元格位置,如下所示:

override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "OutterCardCell", for: indexPath) as! OutterCell
cell.post = posts[indexPath.row]

cell.delegate = self

let cellPosition = self.positionForCell[indexPath.row] ?? 0
cell.innerCollectionView.scrollToItem(at: IndexPath(row: cellPosition, section: 0), at: .left, animated: false)
print (cellPosition)

return cell
}

如果您设法正确设置了所有设置,它应该会在您上下滚动列表时跟踪位置。

关于ios - UICollectionViewCell 中的 UICollectionView 以编程方式,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48059923/

33 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com