问题描述
我正在创建一个 collectionView,它可以有多个部分和一个自动调整大小的单元格。
它在初始布局上运行良好。但是重新加载后,我遇到了三个问题
- 滚动变得断断续续
- 单元格大小改变,单元格相互重叠
- 重新加载数据后内容偏移量发生变化
这是视图控制器代码
class ViewController: UIViewController {
@IBOutlet var collectionView: UICollectionView!
var isLayout = false
let dataSource: [Model] = [
Model(title: "The domains wikipedia.com and wikipedia.org were registered on January 12,2001[21] and January 13,2001[22] respectively,and Wikipedia was launched on January 15,2001,[13] as a single English-language edition at www.wikipedia.com,[23] and announced by Sanger on the Nupedia mailing list.[17] Wikipedia's policy of [24] was codified in its first few months. Otherwise,there were relatively few rules initially and Wikipedia operated independently of Nupedia.[17] Originally,Bomis intended to make Wikipedia a business for profit.[25]"),Model(title: "Otherwise,Model(title: "of Nupedia.[17] Originally,Model(title: "The domains wikipedia.com and wikipedia.org were registered on January 12,"),Model(title: "as a single English-language edition at www.wikipedia.com,[23] and announced by Sanger on the Nupedia mailing list.[17] "),Model(title: " 2001,there were relatively few rules initially and Wikipedia operated independently"),Model(title: "2001[21] and January 13,[23] and announced by Sanger on the Nupedia mailing list.[17] Wikipedia's policy of [24] was codified in "),Model(title: "y 13,there were relatively few rules initially and Wikipedia operated indepe"),Model(title: "domains wikipedia.com and wikipedia.org were registered on January 12,[13] as a singl"),Model(title: "s first few months. Otherwise,there were relatively few rules initially and Wikipedia operated independently "),Model(title: "i as a single English-language edition at www.wikipedia.com,[23] and announced by Sanger on the "),Model(title: "January 13,Model(title: "Eespectively,[23] and announced by Sanger on the Nupedia m"),Model(title: "anguage edition at www.wikipedia.com,Model(title: "anguage edition at www.wiki"),Model(title: "domains"),Model(title: "domains")
]
override func viewDidLoad() {
super.viewDidLoad()
}
override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
if !isLayout {
if let collectionViewLayout = collectionView.collectionViewLayout as? UICollectionViewFlowLayout {
collectionViewLayout.estimatedItemSize = CGSize(width: collectionView.frame.width/2,height: 100)
collectionViewLayout.invalidateLayout()
}
isLayout = true
}
}
@IBAction func reloadData(sender: UIButton) {
collectionView.reloadData()
}
}
// MARK: - Collection view delegate and data source methods
extension ViewController: UICollectionViewDataSource,UICollectionViewDelegateFlowLayout {
func collectionView(_ collectionView: UICollectionView,numberOfItemsInSection section: Int) -> Int {
return dataSource.count
}
func numberOfSections(in collectionView: UICollectionView) -> Int {
return 6
}
func collectionView(_ collectionView: UICollectionView,cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier:"cell",for: indexPath) as! TestCollectionViewCell
cell.titleLabel.text = dataSource[indexPath.item].title
cell.layer.borderWidth = 1
cell.layer.borderColor = UIColor.lightGray.cgColor
if indexPath.section % 2 == 0 {
cell.maxWidth = collectionView.bounds.width/2
} else {
cell.maxWidth = collectionView.bounds.width
}
return cell
}
}
下面是collectionView单元格代码
导入 UIKit
class TestCollectionViewCell: UICollectionViewCell {
@IBOutlet var titleLabel: UILabel!
@IBOutlet private var maxWidthConstraint: NSLayoutConstraint! {
didSet {
maxWidthConstraint.isActive = false
}
}
var maxWidth: CGFloat? = nil {
didSet {
guard let maxWidth = maxWidth else {
return
}
maxWidthConstraint.isActive = true
maxWidthConstraint.constant = maxWidth
}
}
override func awakeFromNib() {
super.awakeFromNib()
contentView.translatesAutoresizingMaskIntoConstraints = false
NSLayoutConstraint.activate([
contentView.leftAnchor.constraint(equalTo: leftAnchor),contentView.rightAnchor.constraint(equalTo: rightAnchor),contentView.topAnchor.constraint(equalTo: topAnchor),contentView.bottomAnchor.constraint(equalTo: bottomAnchor)
])
}
}
这是演示源代码 https://drive.google.com/file/d/1C_LhIsTPRSW19UKMQPJiroAZ8KO4gciW/view
解决方法
- 正确设置您的收藏视图:
let layout = UICollectionViewFlowLayout()
layout.scrollDirection = .vertical //Specify the scroll direction
collectionView.setCollectionViewLayout(layout,animated: true)
collectionView.delaysContentTouches = false
- 在每个部分之间设置您想要的空间:
func collectionView(_ collectionView: UICollectionView,layout collectionViewLayout: UICollectionViewLayout,insetForSectionAt section: Int) -> UIEdgeInsets {
return UIEdgeInsets(top: 0,left: 5,bottom: 0,right: 0)
}
- 在单元格之间设置一些空间:
func collectionView(_ collectionView: UICollectionView,minimumInteritemSpacingForSectionAt section: Int) -> CGFloat {
return 5
}
- 为每个单元格设置自定义宽度和高度。我们将使用两个辅助函数来实现您的需求:
func collectionView(_ collectionView: UICollectionView,layout collectionViewLayout:
UICollectionViewLayout,sizeForItemAt indexPath: IndexPath) -> CGSize {
return calculateWidth(inString: dataSource[indexPath.row].title)+30,height: calculateHeight(inString: dataSource[indexPath.row].title)+30 )
//Calling these functions will return the dimension of each element in your array
//Here I add 30 points because that's what I liked it better. If you don't like it,delete that part.
}
这是您将用于计算将放置在每个集合视图单元格内的文本宽度的函数。它返回它的宽度。
func calculateWidth(inString:String) -> CGFloat{
let messageString = inString
let attributes : [NSAttributedString.Key : Any] = [NSAttributedString.Key(rawValue:
NSAttributedString.Key.font.rawValue) : UIFont.systemFont(ofSize:
universalFont(size: 15))] //If you use a different font/dimension,change it here
let attributedString : NSAttributedString = NSAttributedString(string: messageString,attributes: attributes)
let rect : CGRect = attributedString.boundingRect(with: CGSize(width: 222.0,height: CGFloat.greatestFiniteMagnitude),options: .usesLineFragmentOrigin,context: nil)
let requredSize:CGRect = rect
return requredSize.width
}
这是您将用于计算将放置在每个集合视图单元格内的文本高度的函数。它返回它的高度。
func calculateHeight(inString:String) -> CGFloat{
let messageString = inString
let attributes : [NSAttributedString.Key : Any] = [NSAttributedString.Key(rawValue:
NSAttributedString.Key.font.rawValue) : UIFont.systemFont(ofSize:
universalFont(size: 15))] //If you use a different font/dimension,context: nil)
let requredSize:CGRect = rect
return requredSize.height
}
- 在你的 cellForItemAt 集合中:
cell.textLabel?.sizeToFit()
cell.textLabel?.numberOfLines = 0
,
也许尝试使用UICollectionViewFlowLayout.automaticSize
:
collectionViewLayout.estimatedItemSize = UICollectionViewFlowLayout.automaticSize
collectionViewLayout.invalidateLayout()
更改后,我在模拟器上看不到任何重叠