14

Tôi có lưới cơ bản trong một số UICollectionView. Đó là một bố cục 2 cột, nhiều hàng đơn giản sử dụng UICollectionViewDelegateFlowLayout. Khi một ô được chọn, tôi muốn làm mờ nền, thả ô vào giữa màn hình và sau đó có luồng công việc dựa trên ô đã chọn. Tôi khá mới với UICollectionViews, và tôi không chắc chắn về cách tốt nhất để đi về điều này.Tạo hiệu ứng một ô UICollectionView khi chọn

Tôi có nên có bố cục tùy chỉnh của UICollectionView cho thời điểm một ô được chọn không?

Hoặc là có cách nào tôi có thể làm động các ô đã chọn mà không cần phải tạo ra một bố cục mới

Nếu bất cứ ai có thể chỉ cần làm cho tôi đang diễn ra đúng hướng, tôi nghĩ rằng tôi sẽ được tốt để nghiên cứu làm thế nào để thực hiện nó.

Trả lời

12

Sau khi thử một số giải pháp (và thay vì hacky), tôi đã giải quyết vấn đề này bằng cách viết bố cục UICollectionView của riêng mình. giải pháp trước đó tôi đã cố gắng:

  • Thêm một tùy chỉnh UIView cao hơn các UICollectionView và cố gắng giả tế bào gốc di chuyển bằng cách phủ nó, mờ nền, và hoạt cảnh UIView mới
  • Animate tế bào mà không cần tạo một thương hiệu mới layout

Tôi đã cố gắng tránh nó, nhưng sau khi tôi bắt đầu viết mã nó, điều đó ít đau đớn hơn tôi nghĩ ban đầu.

Đây là mã của tôi, cho bất cứ ai quan tâm:

.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 

Sau đó, trên UICollectionView của bạn, bạn gọi

MyLayout *stackedLayout = [[MyLayout alloc] initWithSelectedCellIndexPath:indexPath]; 
[stackedLayout invalidateLayout]; 
[self.collectionView setCollectionViewLayout:stackedLayout 
            animated:YES]; 

Ảnh động giữa các ô sẽ được xử lý bởi bố cục tùy chỉnh.

+3

Đây không phải là câu trả lời. Có vẻ như bạn có câu trả lời nhưng không muốn chia sẻ. – Fiveagle

+1

@Mark Struzinski bạn có thể chia sẻ giải pháp của bạn không? –

+0

Đó là một đoạn mã khá dài, nhưng tôi không giữ lại vì bất kỳ lý do cụ thể nào. Tôi đã đăng nó ở trên cho bất cứ ai quan tâm. Không chắc tại sao có downvotes ở đây. Giải pháp cuối cùng đã sử dụng một phương pháp được ghi chép đầy đủ trong tài liệu của Apple: http://developer.apple.com/library/ios/#documentation/uikit/reference/UICollectionViewLayout_class/Reference/Reference.html. Tôi đã cố gắng tránh nó bởi vì nó khá là một chút công việc. –

6

Dường như là câu hỏi nhiều phần, vì vậy tôi sẽ trả lời một phần câu hỏi.

  1. UICollectionviewCellskhông tự động điều chỉnh trên nổi bật hoặc lựa chọn. Nó sẽ chỉ cho bạn biết khi các tế bào được đánh dấu hoặc được lựa chọn, với một ngoại lệ:

Đối với hầu hết các phần, quan điểm thu đổi chỉ các thuộc tính của một tế bào để cho biết rằng nó được chọn hoặc nhấn mạnh; nó không thay đổi giao diện trực quan của các ô của bạn, với một ngoại lệ. Nếu thuộc tính của ô có chế độ xem hợp lệ, chế độ xem sẽ hiển thị chế độ xem đó khi ô được đánh dấu hoặc chọn .

Nếu không, bạn phải thực hiện đánh dấu thủ công trực quan. Thường bằng cách điều chỉnh một trong hai .alpha tài sản của toàn bộ tế bào, hoặc trao đổi ra .image tài sản của một nền UIImageView trong tế bào tự sử dụng một hoặc nhiều các phương pháp sau, đều có thể vào trong <UICollectionViewDelegate> Protocol:

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

Đối với phần còn lại của câu hỏi của bạn, tôi muốn tôi có thể giúp đỡ nhiều hơn, nhưng tôi không thông thạo hoạt hình xem tùy chỉnh.

+0

Xin chào. Tôi đã cố gắng để animate từ collectionView: didSelectItemAtIndexPath :. Tuy nhiên, theo câu hỏi, tôi muốn thực sự di chuyển ô đến giữa màn hình để tập trung vào nó. Tôi tự hỏi bây giờ nếu điều này không có nghĩa là tôi nên sử dụng một bộ điều khiển xem phương thức và làm một cái gì đó để làm cho nó xuất hiện các tế bào là hoạt hình. –

Các vấn đề liên quan