14

UICollectionView에 기본 눈금이 있습니다. UICollectionViewDelegateFlowLayout을 사용하는 간단한 2 열, 여러 행 레이아웃입니다. 셀을 선택하면 배경을 어둡게하고 셀을 화면 가운데로 이동 한 다음 선택한 셀을 기반으로 워크 플로를 만들려고합니다. 나는 상당히 새로운 UICollectionViews이고, 이것에 관해 가장 좋은 방법을 확신하지 못합니다.선택시 UICollectionView 셀 애니메이션하기

셀을 선택하면 UICollectionView의 맞춤 레이아웃을 사용해야합니까?

아니면이 사람이 그냥 날 올바른 방향에 갈 수 있다면

가, 내가 실행하는 방법을 연구하는 것이 좋을 것 같아요 새로운 레이아웃을 생성 할 필요없이 선택한 셀 애니메이션을 적용 할 수있는 방법이있다 그것.

답변

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]; 

셀 간의 애니메이션은 맞춤 레이아웃으로 처리됩니다.

+3

이것은 답변이 아닙니다. 답을 갖고 있지만 공유에 관심이없는 것 같습니다. – Fiveagle

+1

@ Mark Struzinski 당신의 솔루션을 공유 할 수 있습니까? –

+0

다소 긴 코드이지만, 어떤 특별한 이유라도 가지고 있지 않습니다. 관심있는 사람을 위해 위에 게시했습니다. 왜 여기에 downvotes가 있었는지 확실하지 않습니다. 최종 해결 방법은 Apple docs : http://developer.apple.com/library/ios/#documentation/uikit/reference/UICollectionViewLayout_class/Reference/Reference.html에서 철저히 문서화 된 방법을 사용했습니다. 꽤 피곤하기 때문에 나는 그것을 피하려고 애썼다. –

6

여러 부분으로 구성된 질문이므로 일부 답변 해 드리겠습니다.

  1. UICollectionviewCells

    자동 하이라이트 또는 선택
    을 조정하지 않습니다. 셀이 강조 표시 또는 선택했을 때 그것은 하나 개의 예외와 함께, 당신을 말할 것이다 : 대부분의 경우

컬렉션보기가 선택하거나 강조 표시되어 있는지 표시하기 위해 셀의 속성을 수정; 한 가지 예외는 있지만 셀의 시각적 모양을 변경하지 않습니다. 셀의 selectedBackgroundView 속성에 유효한보기가 포함되어있는 경우 컬렉션보기는 셀이 강조 표시되거나 이 선택된 경우 해당보기를 표시합니다.

그렇지 않으면 시각적 인 강조 표시를 수동으로 수행해야합니다.

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

: 보통 <UICollectionViewDelegate> 프로토콜에 액세스 할 수있는 다음 방법 중 하나 이상을 사용하여 세포 자체의 배경 UIImageView.image 속성을 전체 셀의 .alpha 특성 중 하나를 조정하거나, 스와핑로 나머지 질문에 대해서는 더 많은 도움이 될 수 있으면 좋겠지 만 사용자 정의보기 애니메이션에 유창하지는 않습니다.

+0

안녕하세요. 나는 이미 collectionView : didSelectItemAtIndexPath :에서 애니 메이팅을 시도했다. 하지만 질문에 초점을 맞추기 위해 실제로 셀을 화면 중앙으로 옮기고 싶습니다. 이제 이것이 모달 뷰 컨트롤러를 사용하여 셀이 움직이는 것처럼 보이게해야한다는 것을 의미하지 않는다면 궁금합니다. –