UICollectionViewCells 在重新排列后重置其大小
UICollectionViewCells are resetting their size after being rearranged
我有一个带有标签的单元格的 UICollectionView,我希望能够通过拖放对它们重新排序。
单元格的大小是用 estimatedItemSize 设置的,因为我希望它们的大小各不相同,具体取决于单元格中文本的大小。我可以让它看起来很好。但是,一旦我使用 collectionView.moveItemAtIndexPath,单元格似乎会采用默认大小。
移动后立即重置 collectionView 的流布局也无法解决问题。
在viewDidLoad
let layout: UICollectionViewFlowLayout = UICollectionViewFlowLayout()
layout.estimatedItemSize = CGSize(width: 100, height: 100)
collectionView.collectionViewLayout = layout
重新排序文本的UIPanGestureRecognizer
func handlePan(sender: UIPanGestureRecognizer) {
let locationPoint = sender.locationInView(collectionView)
if sender.state == UIGestureRecognizerState.Began {
if let indexPath = collectionView.indexPathForItemAtPoint(locationPoint)? {
if let cell = collectionView.cellForItemAtIndexPath(indexPath) {
UIGraphicsBeginImageContext(cell.bounds.size)
cell.layer.renderInContext(UIGraphicsGetCurrentContext())
let cellImage = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
movingCellImage = UIImageView(image: cellImage)
movingCellImage.center = locationPoint
movingCellImage.transform = CGAffineTransformMakeScale(2, 2)
collectionView.addSubview(movingCellImage)
cell.alpha = 0
movingCellOriginalIndexPath = indexPath
}
}
} else if sender.state == UIGestureRecognizerState.Changed {
movingCellImage.center = locationPoint
} else if sender.state == UIGestureRecognizerState.Ended {
if let indexPath = collectionView.indexPathForItemAtPoint(locationPoint)? {
let cell = collectionView.cellForItemAtIndexPath(movingCellOriginalIndexPath)
collectionView.moveItemAtIndexPath(movingCellOriginalIndexPath, toIndexPath: indexPath)
cell?.alpha = 1
}
movingCellImage.removeFromSuperview()
}
}
重新加载动画似乎可以解决问题。
但是 之前的布局会暂时保留...您可能需要创建自定义 UICollectionViewLayout
而不是使用 estimatedSize
.
if let indexPath = collectionView.indexPathForItemAtPoint(locationPoint)? {
let cell = collectionView.cellForItemAtIndexPath(movingCellOriginalIndexPath)
collectionView.moveItemAtIndexPath(movingCellOriginalIndexPath, toIndexPath: indexPath)
cell?.alpha = 1
collectionView.reloadSections(NSIndexSet(index: 0)) // not reloadData
}
[更新]
正如您所指出的,关键是 -collectionView:layout:sizeForItemAtIndexPath:
。
- 不要将
estimatedSize
设置为 UICollectionViewFlowLayout
- 在上面的委托方法中计算每个单元格的大小
像这样:
func collectionView(collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAtIndexPath indexPath: NSIndexPath) -> CGSize {
let str = data[indexPath.item] // string to show in label
// calculate size. you can use -boundingRectWithSize: as well
var txtsize = (str as NSString).sizeWithAttributes([ NSFontAttributeName : UIFont.systemFontOfSize(16)]) // specify label's font
txtsize.width += 10 // add margin if necessary
txtsize.height = 100 // calculated text height or any value you want
return txtsize
}
我有一个带有标签的单元格的 UICollectionView,我希望能够通过拖放对它们重新排序。
单元格的大小是用 estimatedItemSize 设置的,因为我希望它们的大小各不相同,具体取决于单元格中文本的大小。我可以让它看起来很好。但是,一旦我使用 collectionView.moveItemAtIndexPath,单元格似乎会采用默认大小。
移动后立即重置 collectionView 的流布局也无法解决问题。
在viewDidLoad
let layout: UICollectionViewFlowLayout = UICollectionViewFlowLayout()
layout.estimatedItemSize = CGSize(width: 100, height: 100)
collectionView.collectionViewLayout = layout
重新排序文本的UIPanGestureRecognizer
func handlePan(sender: UIPanGestureRecognizer) {
let locationPoint = sender.locationInView(collectionView)
if sender.state == UIGestureRecognizerState.Began {
if let indexPath = collectionView.indexPathForItemAtPoint(locationPoint)? {
if let cell = collectionView.cellForItemAtIndexPath(indexPath) {
UIGraphicsBeginImageContext(cell.bounds.size)
cell.layer.renderInContext(UIGraphicsGetCurrentContext())
let cellImage = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
movingCellImage = UIImageView(image: cellImage)
movingCellImage.center = locationPoint
movingCellImage.transform = CGAffineTransformMakeScale(2, 2)
collectionView.addSubview(movingCellImage)
cell.alpha = 0
movingCellOriginalIndexPath = indexPath
}
}
} else if sender.state == UIGestureRecognizerState.Changed {
movingCellImage.center = locationPoint
} else if sender.state == UIGestureRecognizerState.Ended {
if let indexPath = collectionView.indexPathForItemAtPoint(locationPoint)? {
let cell = collectionView.cellForItemAtIndexPath(movingCellOriginalIndexPath)
collectionView.moveItemAtIndexPath(movingCellOriginalIndexPath, toIndexPath: indexPath)
cell?.alpha = 1
}
movingCellImage.removeFromSuperview()
}
}
重新加载动画似乎可以解决问题。
但是 之前的布局会暂时保留...您可能需要创建自定义 UICollectionViewLayout
而不是使用 estimatedSize
.
if let indexPath = collectionView.indexPathForItemAtPoint(locationPoint)? {
let cell = collectionView.cellForItemAtIndexPath(movingCellOriginalIndexPath)
collectionView.moveItemAtIndexPath(movingCellOriginalIndexPath, toIndexPath: indexPath)
cell?.alpha = 1
collectionView.reloadSections(NSIndexSet(index: 0)) // not reloadData
}
[更新]
正如您所指出的,关键是 -collectionView:layout:sizeForItemAtIndexPath:
。
- 不要将
estimatedSize
设置为UICollectionViewFlowLayout
- 在上面的委托方法中计算每个单元格的大小
像这样:
func collectionView(collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAtIndexPath indexPath: NSIndexPath) -> CGSize {
let str = data[indexPath.item] // string to show in label
// calculate size. you can use -boundingRectWithSize: as well
var txtsize = (str as NSString).sizeWithAttributes([ NSFontAttributeName : UIFont.systemFontOfSize(16)]) // specify label's font
txtsize.width += 10 // add margin if necessary
txtsize.height = 100 // calculated text height or any value you want
return txtsize
}