나는 사용하려고 시도 estimatedItemSize
했지만 estimatedItemSize
셀의 높이와 정확히 일치하지 않으면 셀을 삽입하고 삭제할 때 많은 버그가있었습니다 . 나는 설정을 멈췄다estimatedItemSize
프로토 타입 셀을 사용하여 하고 동적 셀을 구현했습니다. 그 방법은 다음과 같습니다.
이 프로토콜을 작성하십시오.
protocol SizeableCollectionViewCell {
func fittedSize(forConstrainedSize size: CGSize)->CGSize
}
이 프로토콜을 사용자 정의에 구현하십시오 UICollectionViewCell
.
class YourCustomCollectionViewCell: UICollectionViewCell, SizeableCollectionViewCell {
@IBOutlet private var mTitle: UILabel!
@IBOutlet private var mDescription: UILabel!
@IBOutlet private var mContentView: UIView!
@IBOutlet private var mTitleTopConstraint: NSLayoutConstraint!
@IBOutlet private var mDesciptionBottomConstraint: NSLayoutConstraint!
func fittedSize(forConstrainedSize size: CGSize)->CGSize {
let fittedSize: CGSize!
//if height is greatest value, then it's dynamic, so it must be calculated
if size.height == CGFLoat.greatestFiniteMagnitude {
var height: CGFloat = 0
/*now here's where you want to add all the heights up of your views.
apple provides a method called sizeThatFits(size:), but it's not
implemented by default; except for some concrete subclasses such
as UILabel, UIButton, etc. search to see if the classes you use implement
it. here's how it would be used:
*/
height += mTitle.sizeThatFits(size).height
height += mDescription.sizeThatFits(size).height
height += mCustomView.sizeThatFits(size).height //you'll have to implement this in your custom view
//anything that takes up height in the cell has to be included, including top/bottom margin constraints
height += mTitleTopConstraint.constant
height += mDescriptionBottomConstraint.constant
fittedSize = CGSize(width: size.width, height: height)
}
//else width is greatest value, if not, you did something wrong
else {
//do the same thing that's done for height but with width, remember to include leading/trailing margins in calculations
}
return fittedSize
}
}
이제 컨트롤러가에 따르도록 UICollectionViewDelegateFlowLayout
하고, 다음 필드를 갖습니다.
class YourViewController: UIViewController, UICollectionViewDelegateFlowLayout {
private var mCustomCellPrototype = UINib(nibName: <name of the nib file for your custom collectionviewcell>, bundle: nil).instantiate(withOwner: nil, options: nil).first as! SizeableCollectionViewCell
}
데이터를 바인딩 한 다음 해당 데이터가 동적 측정하려는 차원에 어떤 영향을 미치는지 결정하기위한 프로토 타입 셀로 사용됩니다.
마지막 UICollectionViewDelegateFlowLayout's
collectionView(:layout:sizeForItemAt:)
으로 구현해야합니다.
class YourViewController: UIViewController, UICollectionViewDelegateFlowLayout, UICollectionViewDataSource {
private var mDataSource: [CustomModel]
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath)->CGSize {
//bind the prototype cell with the data that corresponds to this index path
mCustomCellPrototype.bind(model: mDataSource[indexPath.row]) //this is the same method you would use to reconfigure the cells that you dequeue in collectionView(:cellForItemAt:). i'm calling it bind
//define the dimension you want constrained
let width = UIScreen.main.bounds.size.width - 20 //the width you want your cells to be
let height = CGFloat.greatestFiniteMagnitude //height has the greatest finite magnitude, so in this code, that means it will be dynamic
let constrainedSize = CGSize(width: width, height: height)
//determine the size the cell will be given this data and return it
return mCustomCellPrototype.fittedSize(forConstrainedSize: constrainedSize)
}
}
그리고 그게 다야. collectionView(:layout:sizeForItemAt:)
이런 식으로 셀 크기를 반환하면 사용하지 않아도되며 estimatedItemSize
셀 삽입 및 삭제가 완벽하게 작동합니다.