初始表加载后,一切正常。但是在插入新单元格并快速向上滚动后,您可以看到一些单元格重新计算其大小(动画)。这真的很奇怪,最多2-3个单元。我使用了带有反转单元格的自下而上的集合视图和自定义流程布局,但它也没有动画。此外,当滚动时,键盘隐藏,所以它可能与它有关..
细胞插入:
self.collectionView?.insertItems(at: [indexPath])
UIView.performWithoutAnimation {
self.collectionView?.reloadItems(at: indexPaths)
self.view.layoutIfNeeded()
}
self.collectionView?.setContentOffset(CGPoint(x: 0, y: 0), animated: true)
问题视频:
override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let newIndex : Int = messagesDataArray.count - 1 - indexPath.item
if messagesDataArray[newIndex].otherPerson == true {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "ConversationCellOtherPerson", for: indexPath) as! ConversationCellOtherPerson
cell.data = messagesDataArray[newIndex]
cell.personImageView.image = otherPersonImage
return cell
} else {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "ConversationCellUser", for: indexPath) as! ConversationCellUser
cell.data = messagesDataArray[newIndex]
return cell
}
}
另外。 ConversationCellUser:
class ConversationCellUser : UICollectionViewCell {
let messageLabel = ConversationLabel()
let mainContainerView = UIView()
let textContainerView : UIView = {
let view = UIView()
view.layer.cornerRadius = 20
return view
}()
var data : MessagesInfo? { didSet { updateCell() } }
func updateCell() {
guard let data = data else { return }
messageLabel.text = data.messageText
}
override init(frame: CGRect) {
super.init(frame: frame)
backgroundColor = .clear
clipsToBounds = true
messageLabel.translatesAutoresizingMaskIntoConstraints = false
textContainerView.translatesAutoresizingMaskIntoConstraints = false
mainContainerView.translatesAutoresizingMaskIntoConstraints = false
mainContainerView.addSubview(textContainerView)
textContainerView.addSubview(messageLabel)
contentView.addSubview(mainContainerView)
NSLayoutConstraint(item: textContainerView, attribute: .right, relatedBy: .equal, toItem: mainContainerView, attribute: .right, multiplier: 1, constant: -10).isActive = true
textContainerView.addConstraintsWithFormat(format: "H:|-14-[v0]-14-|", views: messageLabel)
textContainerView.addConstraintsWithFormat(format: "V:|-10-[v0]-10-|", views: messageLabel)
contentView.addConstraintsWithFormat(format: "H:|[v0]|", views: mainContainerView)
contentView.addConstraintsWithFormat(format: "V:|[v0]|", views: mainContainerView)
textContainerView.backgroundColor = .lightGray
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
override func apply(_ layoutAttributes: UICollectionViewLayoutAttributes) {
super.apply(layoutAttributes)
transform = CGAffineTransform(a: 1, b: 0, c: 0, d: -1, tx: 0, ty: 0)
updateConstraints()
setNeedsUpdateConstraints()
}
}
ConversationLabel:
class ConversationLabel : BaseMessageLabel {
override init(frame: CGRect) {
super.init(frame: frame)
self.textColor = .white
self.font = UIFont(name: "AvenirNext-Medium", size: 14)
self.lineBreakMode = .byWordWrapping
self.numberOfLines = 0
self.preferredMaxLayoutWidth = 200
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
}
SizeForItem:
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
var height : CGFloat = 80
let text = messagesDataArray[indexPath.row].messageText
height = estimateFrameFor(text).height + 20
return CGSize(width: collectionView.bounds.size.width, height: height)
}
private func estimateFrameFor(_ text : String) -> CGRect {
let size = CGSize(width: 200, height: 1000)
return NSString(string: text).boundingRect(with: size, options: .usesLineFragmentOrigin, attributes: [NSFontAttributeName : UIFont(name: "AvenirNext-Medium", size: 14)!], context: nil)
}
我使用的FlowLayout是这样的:
the documentation of AdvertiseCallback class
嘿,我创建了一个带有问题的小项目: http://vimple.co/3c39cb325b9c4ec19173fea015b6cc8b
答案 0 :(得分:2)
无法发表评论,没有足够的代表。但正如评论的那样,请提供ConversationLabel
课程,sizeForItemAtIndexPath
覆盖以及自定义FlowLayout
课程的代码。添加自定义布局类时,很容易忽略某些结果行为。
如果没有给出这些方法,你在这里就不会有太多运气了。当你这样做时,我会查看并更新我的答案。
但是,从视频来看,这是我首先要看的内容:
由于当索引变得可见时,单元格会重新添加到collectionview
的可见部分,因此动画可能是由于您在sizeForItemAtIndexPath
内部应用的大小而可能是如果用于应用大小的任何单元格元素没有足够快地更新,则会延迟。或者由于滞后,动画以某种方式可见,因为每次将单元视图带入视图时都会调用约束重置器(这可能会导致一些滞后,具体取决于设备)。
由于你的apply(_ layoutAttributes: UICollectionViewLayoutAttributes)
覆盖,我建议使用后者。给出文档here:您正在调用updateConstraints()
一次,然后立即使用setNeedsUpdateConstraints()
,当单元格视图变为可见时,会调度updateConstraints()
调用单元格视图的布局(当你看到动画时)。所以你在这里做了两次工作,这可能会添加到动画队列中。或者,由于您还要重置transform属性,因此您可能还在安排一个您可能没有考虑过的额外动画。
最后,虽然这可能暗示了这种行为源于何处,但如果没有自定义的FlowLayout类,就不可能说出来。如上所述here:
如果您继承并实现任何自定义布局属性,则必须 还会覆盖继承的isEqual:方法来比较值 你的财产。在iOS 7及更高版本中,集合视图不会 如果这些属性未更改,则应用布局属性。它 通过比较旧属性来确定属性是否已更改 和使用isEqual:方法的新属性对象。
并且,正如本post about iOS7 and later os builds所述:
由于您覆盖了apply(_ layoutAttributes: UICollectionViewLayoutAttributes)
方法,因此您还应该使用自己的代码覆盖isEqual(_ object: Any?)
method,该代码会按您希望的方式比较布局属性。
isEqual覆盖的example:
override public func isEqual(_ object: Any?) -> Bool {
guard let rhs = object as? DateClass else {
return false
}
let lhs = self
return lhs.date1 == rhs.date1 &&
lhs.date2 == rhs.date2 &&
lhs.date3 == rhs.date3
}
您将DateClass与UICollectionViewLayoutAttributes交换,将覆盖置于UICollectionViewLayoutAttributes子类的范围内。
因此,就我所说的内容而言,似乎可能会在您的代码中意外地过度调用某些方法。或者您可能没有正确地继承UICollectionViewLayoutAttributes。同样,这些是我提供的最佳解决方案。添加缺少的代码,我将更新答案!