14

に基本的なグリッドがありUICollectionViewます。これは、を使用した単純な2列、複数行のレイアウトUICollectionViewDelegateFlowLayoutです。セルを選択したら、背景を暗くして、セルを画面の中央にフロートさせてから、選択したセルに基づいたワークフローを作成します。私はかなり新しいですUICollectionViews、そして私はこれについて行くための最良の方法がわかりません。

UICollectionViewセルが選択されたときののカスタムレイアウトが必要ですか?

または、新しいレイアウトを作成せずに、選択したセルをアニメーション化する方法はありますか?

誰かが私を正しい方向に向かわせることができれば、それを実行する方法を研究するのは良いことだと思います。

4

2 に答える 2

12

いくつかの(そしてかなりハックな)ソリューションを試した後、独自のUICollectionViewレイアウトを作成することでこれを解決しました。私が試みた以前の解決策:

  • 上にカスタムUIViewを追加しUICollectionView、元のセルをオーバーレイし、背景を薄暗くし、新しい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];

セル間のアニメーションは、カスタム レイアウトによって処理されます。

于 2013-05-06T19:01:29.667 に答える
6

複数の部分からなる質問のようですので、その一部にお答えします。

  1. UICollectionviewCells ハイライトまたは選択で自動的に調整しないでください。セルが強調表示または選択されている場合にのみ通知されますが、1 つの例外があります。

ほとんどの場合、コレクション ビューはセルのプロパティのみを変更して、セルが選択または強調表示されていることを示します。1 つの例外を除いて、セルの外観は変わりません。セルのselectedBackgroundViewプロパティに有効なビューが含まれている場合、セルが強調表示または選択されると、コレクション ビューにそのビューが表示されます。

それ以外の場合は、視覚的な強調表示を手動で行う必要があります。通常、.alphaセル全体のプロパティを調整するか、プロトコルでアクセスできる次のメソッドの 1 つ以上を使用して、セル自体.imageの背景のプロパティを交換します。UIImageView<UICollectionViewDelegate>

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

あなたの質問の残りの部分については、私はもっと役に立ちたいと思っていますが、私はカスタムビューアニメーションに堪能ではありません.

于 2013-02-05T05:34:47.820 に答える