IT Share you

UICollectionView : 선택시 셀 크기 변경 애니메이션

shareyou 2020. 11. 25. 21:37
반응형

UICollectionView : 선택시 셀 크기 변경 애니메이션


내가하고 싶은 것은 UICollectionViewCell의 크기를 변경하고 셀이 선택 될 때 변경 사항을 애니메이션화하는 것입니다. 셀을 선택한 것으로 표시 한 collectionView: didSelectItemAtIndexPath:다음 reloadDataUICollectionView 를 호출 하여 선택한 셀을 다른 크기 로 표시하여 애니메이션없이 이미 수행했습니다 .

그럼에도 불구하고 이것은 한 번에 발생하며 크기 변경을 애니메이션으로 만드는 방법에 대한 단서가 없습니다. 어떤 아이디어?

나는 이미 selection 에서 Animate uicollectionview 셀을 찾았 지만 대답은 저에게 구체적이지 않았으며 제 경우에도 도움이 될 수 있는지 아직 파악하지 못했습니다.


[UIView transitionWithView:collectionView 
                  duration:.5 
                   options:UIViewAnimationOptionTransitionCurlUp 
                animations:^{

    //any animatable attribute here.
    cell.frame = CGRectMake(3, 14, 100, 100);

} completion:^(BOOL finished) {

    //whatever you want to do upon completion

}];

당신의 didselectItemAtIndexPath방법 안에서 그 라인을 따라 무언가를 가지고 놀아 라 .


Chase Roberts의 도움으로 이제 내 문제에 대한 해결책을 찾았습니다. 내 코드는 기본적으로 다음과 같습니다.

// Prepare for animation

[self.collectionView.collectionViewLayout invalidateLayout];
UICollectionViewCell *__weak cell = [self.collectionView cellForItemAtIndexPath:indexPath]; // Avoid retain cycles
void (^animateChangeWidth)() = ^()
{
    CGRect frame = cell.frame;
    frame.size = cell.intrinsicContentSize;
    cell.frame = frame;
};

// Animate

[UIView transitionWithView:cellToChangeSize duration:0.1f options: UIViewAnimationOptionCurveLinear animations:animateChangeWidth completion:nil];

추가 설명 :

  1. 가장 중요한 단계 중 하나 는 사용중인 invalidateLayout에 대한 통화입니다 UICollectionView.collectionViewLayout. 잊어 버리면 컬렉션의 경계를 넘어 세포가 성장할 가능성이 높습니다. 이는 아마도 가장 원하지 않는 일입니다. 또한 코드가 어느 시점에서 레이아웃에 셀의 새로운 크기를 표시해야 함을 고려하십시오. 제 경우에는 (사용하고 있습니다 UICollectionViewFlowLayout) collectionView:layout:sizeForItemAtIndexPath수정 된 셀의 새로운 크기를 반영하도록 방법을 조정했습니다 . 해당 부분을 잊어 버리면 먼저 호출 invalidateLayout한 다음 크기 변경에 애니메이션을 적용하려고 하면 셀 크기에 아무런 변화가 없습니다.

  2. (적어도 나에게는) 가장 이상하지만 중요한 것은 애니메이션 블록 내부에서 호출 invalidateLayout 하지 않는다는 것 입니다. 그렇게하면 애니메이션이 매끄럽게 표시되지 않지만 글리치 및 깜박임이 표시됩니다.

  3. 전체 컬렉션이 아니라 애니메이션을 적용하려는 셀이기 때문에 전체 컬렉션 뷰가 아니라에 대한 인수로 셀을 사용하여 UIViews transitionWithView:duration:options:animations:completion:메서드 를 호출해야합니다 transitionWithView.

  4. intrinsicContentSize원하는 크기를 반환하기 위해 셀 방법을 사용 했습니다. 제 경우에는 셀의 선택 상태에 따라 버튼을 표시하거나 숨기도록 셀의 너비를 늘리거나 줄였습니다.

나는 이것이 어떤 사람들에게 도움이되기를 바랍니다. 저에게는 애니메이션이 제대로 작동하도록하는 방법을 알아내는 데 몇 시간이 걸렸기 때문에 다른 사람들을 시간 소모적 인 부담에서 해방하려고 노력합니다.


셀 크기에 애니메이션을 적용하는 것은 테이블보기와 동일한 방식으로 콜렉션보기에 대해 작동합니다. 셀 크기에 애니메이션을 적용하려면 셀의 상태를 반영하는 데이터 모델을 사용하고 (제 경우에는 플래그 (CollectionViewCellExpanded, CollectionViewCellCollapsed)를 사용하고 그에 따라 CGSize를 반환합니다.

performBathUpdates 호출을 호출하고 비우면 뷰가 자동으로 애니메이션됩니다.

- (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath
{
    [collectionView performBatchUpdates:^{
        // append your data model to return a larger size for
        // cell at this index path
    } completion:^(BOOL finished) {

    }];
}

-setCollectionViewLayout:animated:동일한 컬렉션 뷰 레이아웃의 새 인스턴스를 만드는 데 사용하여 변경 사항을 애니메이션 으로 만들었습니다.

예를 들어를 사용하는 UICollectionViewFlowLayout경우 다음을 수행합니다.

// Make sure that your datasource/delegate are up-to-date first

// Then animate the layout changes
[collectionView setCollectionViewLayout:[[UICollectionViewFlowLayout alloc] init] animated:YES];

이것은 내가 찾은 가장 간단한 솔루션입니다-매력처럼 작동합니다. 부드러운 애니메이션, 레이아웃을 엉망으로 만들지 않습니다.

빠른

    collectionView.performBatchUpdates({}){}

Obj-C

    [collectionView performBatchUpdates:^{ } completion:^(BOOL finished) { }];

블록 (Swift의 클로저)은 의도적으로 비워 두어야합니다!


A good way to animate the cell size is to override isSelected in the collectionViewCell itself.

class CollectionViewCell: UICollectionViewCell {

    override var isHighlighted: Bool {
        didSet {
            if isHighlighted {
                UIView.animate(withDuration: 0.2, delay: 0, options: .curveEaseOut, animations: {
                    self.transform = CGAffineTransform(scaleX: 0.95, y: 0.95)
                }, completion: nil)
            } else {
                UIView.animate(withDuration: 0.2, delay: 0, options: .curveEaseOut, animations: {
                    self.transform = CGAffineTransform(scaleX: 1, y: 1)
                }, completion: nil)
            }
        }
    }

}

Using performBatchUpdates will not animate the layout of the cell contents. Instead, you can use the following:

    collectionView.collectionViewLayout.invalidateLayout()

    UIView.animate(
        withDuration: 0.4,
        delay: 0.0,
        usingSpringWithDamping: 1.0,
        initialSpringVelocity: 0.0,
        options: UIViewAnimationOptions(),
        animations: {
            self.collectionView.layoutIfNeeded()
        },
        completion: nil
    )

This gives a very smooth animation.

This is similar to Ignatius Tremor's answer, but the transition animation did not work properly for me.

See https://github.com/cnoon/CollectionViewAnimations for a complete solution.


This worked for me.

    collectionView.performBatchUpdates({ () -> Void in
        let ctx = UICollectionViewFlowLayoutInvalidationContext()
        ctx.invalidateFlowLayoutDelegateMetrics = true
        self.collectionView!.collectionViewLayout.invalidateLayoutWithContext(ctx)
    }) { (_: Bool) -> Void in
    }

참고URL : https://stackoverflow.com/questions/13780153/uicollectionview-animate-cell-size-change-on-selection

반응형