2013-07-20 48 views
20

Tôi muốn các mục trong số UICollectionView của mình hoạt hình để xem khi người dùng cuộn qua danh sách (Tôi đang sử dụng lớp con của UICollectionViewFlowLayout).UICollectionVIew: Animate các ô khi chúng cuộn trong

Tôi chỉ định vị trí trong Trình quản lý bố cục, những gì tôi muốn có thể thực hiện là chỉ định biến đổi ban đầu và áp dụng cho hoạt ảnh vào đúng thời điểm (khi ô xuất hiện lần đầu trên màn hình). Để xem hiệu quả của tôi, hãy xem ứng dụng Google Plus trên iOS. Lý tưởng là một biến đổi khác nhau tùy thuộc vào vị trí của ô.

Tôi dường như không tìm được cách nào để tìm ra thời điểm hiển thị ô (không tương đương willDisplayCell vì có trên UITableView) hoặc bất kỳ gợi ý nào về nơi cần thực hiện điều này.

Mọi đề xuất?

Bạn có thể chỉ là về làm ra các hình ảnh động trong Google Plus trong ảnh chụp màn hình này: Example in the Google Plus App

Ngoài ra, hãy nhìn vào iPhoto trên iPad. Tôi không biết nếu họ đang sử dụng một UIcollectionView (có lẽ không, vì nó làm việc trên iOS5) nhưng đây là loại nếu hiệu ứng tôi đang tìm kiếm, các bức ảnh xuất hiện để bay từ bên phải.

+0

Hey u đã kết thúc nhận được một câu trả lời cho điều đó? Tôi đang cố gắng thực hiện cùng một hành vi, sẽ đánh giá cao sự giúp đỡ của bạn. –

+0

Không, xin lỗi - Tôi đã sử dụng chế độ xem cuộn tiêu chuẩn. – Marc

+0

@JackKapow, tôi đã đăng câu trả lời dưới đây có thể hữu ích. – Cezar

Trả lời

36

Bạn có thể đạt được hiệu ứng này độc lập với bố cục tùy chỉnh.

Mã hoạt hình nên đi bên collectionView:cellForItemAtIndexPath:

Khi một tế bào được dequeued, frame của nó sẽ được thiết lập với những gì được quy định trong cách bố trí của bạn. Bạn có thể lưu trữ nó trong một biến tạm thời là số frame cuối cùng cho ô. Sau đó, bạn có thể đặt cell.frame thành vị trí ban đầu bên ngoài màn hình và sau đó làm động đến vị trí cuối cùng mong muốn. Một cái gì đó dọc theo dòng:

- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath { 

    UICollectionView *cell = [collectionView dequeueReusableCellWithReuseIdentifier:@"Cell" forIndexPath:indexPath]; 

    CGRect finalCellFrame = cell.frame; 
    //check the scrolling direction to verify from which side of the screen the cell should come. 
    CGPoint translation = [collectionView.panGestureRecognizer translationInView:collectionView.superview]; 
    if (translation.x > 0) { 
     cell.frame = CGRectMake(finalCellFrame.origin.x - 1000, - 500.0f, 0, 0); 
    } else { 
     cell.frame = CGRectMake(finalCellFrame.origin.x + 1000, - 500.0f, 0, 0); 
    } 

    [UIView animateWithDuration:0.5f animations:^(void){ 
     cell.frame = finalCellFrame; 
    }]; 

    return cell; 
} 

Đoạn mã trên sẽ động tế bào trên một ngang UICollectionView, đến từ phía trên cùng của màn hình, và từ cả hai phía, tùy thuộc vào hướng di chuyển. Bạn cũng có thể kiểm tra hiện tại indexPath để các ô hoạt ảnh từ các vị trí khác nhau trên các bố cục phức tạp hơn, cũng như tạo các thuộc tính khác cùng với khung hoặc áp dụng biến đổi.

+0

Hey! cảm ơn ! Tôi chơi với nó một chút và bây giờ nó trông tuyệt vời! Tôi sẽ cho bạn biết nếu tôi tìm thấy bất kỳ vấn đề, cảm ơn allot !!!! –

+0

Bạn có một ý tưởng làm thế nào để làm cho nó chỉ hoạt hình một lần? tôi có nghĩa là khi tôi di chuyển xuống chỉ cho lần đầu tiên tôi muốn nó để animate - và sau đó tôi muốn chỉ các tế bào mới để animate (chính xác như trong google +) –

+2

Tôi biết những gì bạn có ý nghĩa. Trong Google +, điều có thể xảy ra là chúng hoạt ảnh khi nội dung mới được chèn vào nguồn dữ liệu CollectionView. Để ngăn hoạt ảnh một lần nữa khi cuộn, tôi giả sử bạn cần lưu trữ một mảng cờ và đặt giá trị của chúng cho mỗi indexPath đã được làm động. Khi khử một ô cho một indexPath đã cho, bạn sẽ kiểm tra mảng đó để xem liệu bạn có nên tạo hiệu ứng động không. – Cezar

6

Bạn cần ghi đè initialLayoutAttributesForAppearingItemAtIndexPath: trong bố cục chế độ xem bộ sưu tập của mình. Ở đây bạn có thể đặt bất kỳ thuộc tính nào trên mục thuộc tính bố cục (bao gồm cả biến đổi) sẽ được làm động đến các thuộc tính thực tế sau khi ô đã xuất hiện.

Nếu đối tượng thuộc tính bố cục chuẩn không cung cấp cho bạn đủ tùy chọn, bạn có thể phân lớp, thêm thuộc tính bổ sung và ghi đè applyLayoutAttributes: trên ô của bạn để chọn các thuộc tính bổ sung.

Điều này sẽ chỉ hoạt động khi bạn thêm ô vào chế độ xem bộ sưu tập.

Để chuyển đổi được áp dụng cho ô khi bạn cuộn xuống chế độ xem bộ sưu tập, tôi xem xét áp dụng chúng trực tiếp vào ô (tại cellForItem ...) hoặc trong thuộc tính bố cục, có thể là thuộc tính được gọi là initialTransform. Khi áp dụng các thuộc tính bố trí cho ô, bạn hãy kiểm tra initialTransform, áp dụng nó, sau đó đặt nó thành nhận dạng, sau đó kích hoạt một hoạt ảnh để chuyển đổi danh tính, vì vậy nó sẽ chỉ được áp dụng khi ô được cuộn đầu tiên màn. Tôi đã không thực hiện bất cứ điều gì như thế này, nó chỉ là một đoán như thế nào tôi sẽ làm điều đó.

+0

Nếu tôi đặt điểm ngắt tại đây, nó chỉ được gọi khi màn hình xoay. Các ý kiến ​​tiêu đề dường như chỉ ra điều này quá. Có cái gì khác tôi cần phải cấu hình? Tôi đang phân lớp UICollectionViewFlowLayout. – Marc

+0

Nó sẽ được gọi khi thêm các mục vào dạng xem hoặc khi di chuyển. – jrturton

+2

Theo tài liệu, phương pháp này được gọi khi dữ liệu thay đổi hoặc khi chế độ xem bộ sưu tập cần vẽ lại, không phải khi cuộn - trừ khi tôi đang làm gì đó sai? Bạn có thể xác nhận bạn nhận được cuộc gọi lại này khi bạn cuộn không? Trích dẫn "** Khi dữ liệu trong chế độ xem bộ sưu tập thay đổi và mục sẽ được chèn hoặc xóa, chế độ xem bộ sưu tập sẽ yêu cầu đối tượng bố trí của nó cập nhật thông tin bố cục. **" Từ http://developer.apple. com/library/ios/documentation/uikit/reference/UICollectionViewLayout_class/Tham khảo/Reference.html – Marc

3

Như Marc đã đề cập trong nhận xét, rằng anh ấy đã kết thúc bằng cách sử dụng chế độ xem cuộn tôi muốn hiển thị cách thực hiện với chế độ xem bảng chuẩn. Nó không phải là hiệu ứng tương tự như được thấy trong google + nhưng có thể được điều chỉnh dễ dàng.

-(void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath 
{ 
    static CGFloat duration = .5; 
    static NSUInteger xOffset = 50; 
    static NSUInteger yOffset = 200; 
    if(scrollDirection == STAScrollDirectionDown && lastAnimatedIndex < indexPath.row) 
    { 
     cell.frame = CGRectMake(cell.frame.origin.x - xOffset, cell.frame.origin.y+yOffset, cell.frame.size.width, cell.frame.size.height); 
     [UIView animateWithDuration:duration 
         animations:^{ 
      cell.frame = CGRectMake(cell.frame.origin.x + xOffset, cell.frame.origin.y - yOffset, cell.frame.size.width, cell.frame.size.height); 
     } completion:^(BOOL finished) { 
      lastAnimatedIndex = indexPath.row; 
     }]; 
    } 
} 

Ngay trước khi ô được hiển thị, chúng tôi chỉ định một khoảng bù (và có thể là một vòng quay) cho mỗi ô và chúng tôi quay lại cài đặt trước đó.


một chút thú vị hơn ví dụ:

-(void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath 
{ 
    CATransform3D rotation = CATransform3DMakeRotation((90.0*M_PI)/180, .0, 0.5, 0.5); 
    cell.contentView.alpha = 0.8; 
    cell.contentView.layer.transform = rotation; 
    cell.contentView.layer.anchorPoint = CGPointMake(0, 0.5); 

    [UIView animateWithDuration:.5 
        animations:^{ 
         cell.contentView.layer.transform = CATransform3DIdentity; 
         cell.contentView.alpha = 1; 
         cell.contentView.layer.shadowOffset = CGSizeMake(0, 0); 
        } completion:^(BOOL finished) { 
        }]; 
} 
+0

Tôi không biết về một 'cellWillAppear' – vikingosegundo

+0

Xin lỗi tôi 'có nghĩa là cellWillDisplay Tôi chỉ nhầm lẫn tên với viewWillAppear, kiểm tra hình ảnh này: http://postimg.org/image/a2g02xgbl/ – Chlebta

+0

Tạo một câu hỏi mới, đăng mã của bạn, mô tả những gì bạn muốn đạt được và những gì bạn thấy thay thế. – vikingosegundo