首页 > 解决方案 > 在视图控制器演示期间为 collectionView 布局设置动画

问题描述

我正在尝试呈现一个动画视图控制器,其动画UIViewControllerAnimatedTransitioning从 alpha 0 到 1;同时将其集合视图从一种布局设置为另一种布局。这两种布局仅在节插入和行间距方面有所不同。

以下是从一种布局移动到另一种布局的代码:

private var useAfterLayout = false
private let layoutBefore = (
    sectionInset: UIEdgeInsets(top: 100, left: 3, bottom: 3, right: 3),
    lineSpacing: CGFloat(10.0)
)

private let layoutAfter = (
    sectionInset: UIEdgeInsets(top: 3, left: 3, bottom: 3, right: 3),
    lineSpacing: CGFloat(3.0)
)

func animateToFinalLayout() {
    useAfterLayout = true
    collectionView.performBatchUpdates({
        collectionView.collectionViewLayout.invalidateLayout()
        collectionView.setCollectionViewLayout(collectionView.collectionViewLayout, animated: true)
    }, completion: nil)
}

public func collectionView(
    _ collectionView: UICollectionView,
    layout collectionViewLayout: UICollectionViewLayout,
    insetForSectionAt section: Int
) -> UIEdgeInsets {
    useAfterLayout ? layoutAfter.sectionInset : layoutBefore.sectionInset
}

public func collectionView(
    _ collectionView: UICollectionView,
    layout collectionViewLayout: UICollectionViewLayout,
    minimumLineSpacingForSectionAt section: Int)
    -> CGFloat {
    useAfterLayout ? layoutAfter.lineSpacing : layoutBefore.lineSpacing
}

我已经尝试在`animateTransition(using:) 中的动画块中调用该animateToFinalLayout方法viewWillAppear(_:),但是视图控制器在出现时只有最终布局。

UIView.animate(withDuration: animationDuration, delay: 0.0, options: .curveEaseOut, animations: {
    toView.center = transitionContext.containerView.center
    toView.alpha = 1.0
    animatedViewController?.animatePresentation()
}, completion: { didComplete in
    transitionContext.completeTransition(didComplete)
})

将调用放入viewDidAppear(_:)动画布局中,但仅在演示动画完成后:

怎样才能同步两个动画?

标签: iosswiftuicollectionviewuikitios-animations

解决方案


正如此评论所暗示的,使用以下代码可以使两个动画完美同步。

override func viewWillAppear(_ animated: Bool) {
    super.viewWillAppear(animated)
    
    DispatchQueue.main.async {
        UIView.animate(withDuration: 0.35, delay: 0.0, options: .curveEaseOut, animations: {
            self.animateToFinalLayout()
        }, completion: nil)
    }
}

推荐阅读