我有一个水平集合视图,每个单元格都有自己的宽度。我使用默认的UICollectionViewFlowLayout。重新排列时,细胞继承了在此运动过程中覆盖的细胞宽度,这是我不想要的。任何想法,如何避免这种行为?
答案 0 :(得分:3)
因此,如果您使用不同大小的单元格的UICollectionView,并且您希望在使用标准UICollectionViewFlowLayout移动时保持其大小,请使用:
extension UICollectionViewFlowLayout {
@available(iOS 9.0, *)
open override func invalidationContext(forInteractivelyMovingItems targetIndexPaths: [IndexPath], withTargetPosition targetPosition: CGPoint, previousIndexPaths: [IndexPath], previousPosition: CGPoint) -> UICollectionViewLayoutInvalidationContext {
let context = super.invalidationContext(forInteractivelyMovingItems: targetIndexPaths, withTargetPosition: targetPosition, previousIndexPaths: previousIndexPaths, previousPosition: previousPosition)
//Check that the movement has actually happeneds
if previousIndexPaths.first!.item != targetIndexPaths.first!.item {
collectionView?.dataSource?.collectionView?(collectionView!, moveItemAt: previousIndexPaths.first!, to: targetIndexPaths.last!)
}
return context
}
open override func invalidationContextForEndingInteractiveMovementOfItems(toFinalIndexPaths indexPaths: [IndexPath], previousIndexPaths: [IndexPath], movementCancelled: Bool) -> UICollectionViewLayoutInvalidationContext {
return super.invalidationContextForEndingInteractiveMovementOfItems(toFinalIndexPaths: indexPaths, previousIndexPaths: previousIndexPaths, movementCancelled: movementCancelled)
}
@available(iOS 9.0, *) //If you'd like to apply some formatting as the dimming of the movable cell
open override func layoutAttributesForInteractivelyMovingItem(at indexPath: IndexPath, withTargetPosition position: CGPoint) -> UICollectionViewLayoutAttributes {
let attributes = super.layoutAttributesForInteractivelyMovingItem(at: indexPath, withTargetPosition: position)
attributes.alpha = 0.8
return attributes
}
}
在你的控制器的moveItemAt方法中,不要忘记检查压力状态是否改变如下:
override func collectionView(_ collectionView: UICollectionView, moveItemAt sourceIndexPath: IndexPath,
to destinationIndexPath: IndexPath) {
if #available(iOS 9.0, *) {
if self.longPressureGestureRecognizer.state == .ended {
return
}
//Update your data
data.moveItem(at: sourceIndexPath.row, to: destinationIndexPath.row)
}
}
答案 1 :(得分:0)
我通过使用collectionView:targetIndexPathForMoveFromItemAtIndexPath:toProposedIndexPath:
来解决这个问题,如果我的行/部分数据的副本不存在,我会创建它,然后更新副本,就好像建议的移动是实际移动一样。我的collectionView:layout:sizeForItemAtIndexPath:
会使用该副本(如果存在)。我会在collectionView:moveItemAtIndexPath:toIndexPath:
中将副本设置为nil,以便视图将返回使用“原始”行/节数据进行大小调整。因此,在移动之前,期间和之后,所有尺寸看起来都是正确的。
根据要求,这是我的代码:
- (NSIndexPath *)collectionView:(UICollectionView *)collectionView targetIndexPathForMoveFromItemAtIndexPath:(NSIndexPath *)originalIndexPath toProposedIndexPath:(NSIndexPath *)proposedIndexPath
{
if (nil == _movingSections)
_movingSections = [_sections copy];
NSMutableArray *section = [_movingSections.sections objectAtIndex:originalIndexPath.section];
id obj = [section objectAtIndex:originalIndexPath.row];
[section removeObjectAtIndex:originalIndexPath.row];
section = [_movingSections.sections objectAtIndex:proposedIndexPath.section];
if (proposedIndexPath.row < [section count])
[section insertObject:obj atIndex:proposedIndexPath.row];
else
[section addObject:obj];
return proposedIndexPath;
}
当_movingSections为非零时,我还更新了collectionView:layout:sizeForItemAtIndexPath:
以使用_movingSections而不是_sections。在collectionView:moveItemAtIndexPath:toIndexPath:
中,我将_movingSections设置为nil。就是这样!
我应该补充一点,我最终放弃了这个方法,因为我的部分可以比设备宽度更宽,这可以正常工作,直到你移动东西,并且在那一点上UICollectionViewFlowLayout想要均匀地分隔单元格而不管你的宽度提供了。相反,我转而使用UIScrollView,现在我的代码更简单,而且我不再与UICollectionViewFlowLayout抗争。我考虑过滚动自己的UICollectionViewLayout,但这并没有使我的代码更简单。