我在UICollectionView中有一个基本的网格.这是一个简单的2列,使用UICollectionViewDelegateFlowLayout的多行布局.选择单元格后,我想对背景变暗,将单元格浮动到屏幕中心,然后根据所选单元格创建一个工作流程.我对UICollectionViews来说相当新鲜,我不知道最好的办法.
UICollectionView的自定义布局是否在选择单元格时有效?
或者有一种我可以为所选单元格动画而不必创建新布局的方式
如果有人能让我走正确的方向,我想我会很好的研究如何执行它.
解决方法
在尝试了几个(而且很奇怪的)解决方案之后,我通过编写自己的UICollectionView布局解决了这个问题.我尝试过的以前的解决方案
>在UICollectionView顶部添加一个自定义UIView,并尝试通过覆盖原始单元格进行移动,使背景变暗,并使新的UIView动画化
>在不创建全新布局的情况下动画化单元格
我试图避免它,但是在我编码之后,它比我原来想象的痛苦要少得多.
这是我的代码,任何有兴趣的人:
.H:
@interface FMStackedLayout : UICollectionViewLayout @property(nonatomic,assign) CGPoint center; @property(nonatomic,assign) NSInteger cellCount; -(id)initWithSelectedCellIndexPath:(NSIndexPath *)indexPath; @end
.M:
#define ITEM_WIDTH 128.0f #define ITEM_HEIGHT 180.0f static NSUInteger const RotationCount = 32; static NSUInteger const RotationStride = 3; static NSUInteger const PhotoCellBaseZIndex = 100; @interface FMStackedLayout () @property(strong,nonatomic) NSArray *rotations; @property(strong,nonatomic) NSIndexPath *selectedIndexPath; @end @implementation FMStackedLayout #pragma mark - Lifecycle -(id)initWithSelectedCellIndexPath:(NSIndexPath *)indexPath{ self = [super init]; if (self) { self.selectedIndexPath = indexPath; [self setup]; } return self; } -(id)initWithCoder:(NSCoder *)aDecoder{ self = [super init]; if (self){ [self setup]; } return self; } -(void)setup{ NSMutableArray *rotations = [NSMutableArray arrayWithCapacity:RotationCount]; CGFloat percentage = 0.0f; for (NSUInteger i = 0; i < RotationCount; i++) { // Ensure that each angle is different enough to be seen CGFloat newPercentage = 0.0f; do { newPercentage = ((CGFloat)(arc4random() % 220) - 110) * 0.0001f; } while (fabsf(percentage - newPercentage) < 0.006); percentage = newPercentage; CGFloat angle = 2 * M_PI * (1.0f + percentage); CATransform3D transform = CATransform3DMakeRotation(angle,0.0f,1.0f); [rotations addObject:[NSValue valueWithCATransform3D:transform]]; } self.rotations = rotations; } #pragma mark - Layout -(void)prepareLayout{ [super prepareLayout]; CGSize size = self.collectionView.frame.size; self.cellCount = [self.collectionView numberOfItemsInSection:0]; self.center = CGPointMake(size.width / 2.0,size.height / 2.0); } -(CGSize)collectionViewContentSize{ return self.collectionView.frame.size; } -(UICollectionViewLayoutAttributes *)layoutAttributesForItemAtIndexPath:(NSIndexPath *)indexPath{ UICollectionViewLayoutAttributes *attributes = [UICollectionViewLayoutAttributes layoutAttributesForCellWithIndexPath:indexPath]; attributes.size = CGSizeMake(ITEM_WIDTH,ITEM_HEIGHT); attributes.center = self.center; if (indexPath.item == self.selectedIndexPath.item) { attributes.zIndex = 100; }else{ attributes.transform3D = [self transformForPersonViewAtIndex:indexPath]; } return attributes; } -(NSArray *)layoutAttributesForElementsInRect:(CGRect)rect{ NSMutableArray *attributes = [NSMutableArray array]; for (NSInteger i = 0; i < self.cellCount; i++) { NSIndexPath *indexPath = [NSIndexPath indexPathForItem:i inSection:0]; [attributes addObject:[self layoutAttributesForItemAtIndexPath:indexPath]]; } return attributes; } #pragma mark - Private -(CATransform3D)transformForPersonViewAtIndex:(NSIndexPath *)indexPath{ NSInteger offset = (indexPath.section * RotationStride + indexPath.item); return [self.rotations[offset % RotationCount] CATransform3DValue]; } @end
然后,在你的UICollectionView上,你打电话
MyLayout *stackedLayout = [[MyLayout alloc] initWithSelectedCellIndexPath:indexPath]; [stackedLayout invalidateLayout]; [self.collectionView setCollectionViewLayout:stackedLayout animated:YES];
单元格之间的动画将由自定义布局处理.