簡體   English   中英

在選擇時為UICollectionView單元設置動畫

[英]Animate a UICollectionView cell on selection

我在UICollectionView中有一個基UICollectionView格。 這是一個使用UICollectionViewDelegateFlowLayout的簡單的2列多行布局。 選擇單元格后,我想調暗背景,將單元格浮動到屏幕中心,然后根據所選單元格建立工作流程。 我是UICollectionViews ,我不確定最好的方法。

我是否應該在選擇單元格時使用UICollectionView的自定義布局?

或者有一種方法可以動畫選定的單元格,而無需創建新的布局

如果有人能讓我朝着正確的方向前進,我想我會很好地研究如何執行它。

在嘗試了幾個(而不是hacky)解決方案后,我通過編寫自己的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, 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];

單元格之間的動畫將由自定義布局處理。

似乎是一個多部分的問題,所以我會回答它的一部分。

  1. UICollectionviewCells 不會突出顯示選擇時 自動調整 它只會在突出顯示或選擇單元格時告訴您,但有一個例外:

在大多數情況下,集合視圖僅修改單元格的屬性以指示它已被選中或突出顯示; 除了一個例外,它不會改變細胞的視覺外觀。 如果單元格的selectedBackgroundView屬性包含有效視圖,則集合視圖會在突出顯示或選擇單元格時顯示該視圖。

否則,您必須手動進行視覺突出顯示。 通常通過調節.alpha整個單元的特性,或換出.image背景的屬性UIImageView使用下列方法,其是在可訪問的一個或多個小區中本身<UICollectionViewDelegate>協議:

collectionView:didDeselectItemAtIndexPath:
collectionView:didHighlightItemAtIndexPath:
collectionView:didSelectItemAtIndexPath:
collectionView:didUnhighlightItemAtIndexPath:
collectionView:shouldDeselectItemAtIndexPath:
collectionView:shouldHighlightItemAtIndexPath:
collectionView:shouldSelectItemAtIndexPath:

至於你提出的其他問題,我希望能提供更多幫助,但我對自定義視圖動畫不太熟悉。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM