【问题标题】:Correct transition of subviews in UICollectionViewCellUICollectionViewCell 中子视图的正确转换
【发布时间】:2014-11-18 01:58:01
【问题描述】:

我正在使用 layoutToLayout 导航过渡 (useLayoutToLayoutNavigationTransitions),但动画不流畅;在过渡期间,单元格的子视图会奇怪地跳来跳去:

可能出了什么问题?

我的 collectionviewcell 类如下所示:

private class PageCell : UICollectionViewCell {
    override init(frame: CGRect) {
        super.init(frame: frame)
    }

    required init(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)
    }

    var viewController : UIViewController? {
        willSet {
            for view in self.contentView.subviews as [UIView] {
                view.removeFromSuperview()
            }
        }

        didSet {
            if let view = viewController?.view {
                view.frame = self.contentView.bounds
                self.contentView.addSubview(view)
                self.contentView.autoresizingMask = .FlexibleHeight | .FlexibleWidth;
                view.autoresizingMask = .FlexibleHeight | .FlexibleWidth;
            }
        }
    }
}

【问题讨论】:

    标签: swift uicollectionview uicollectionviewcell


    【解决方案1】:

    我通过使用TLTransitionLayout 转换到其他布局解决了这个问题。它使动画对于更复杂的单元格看起来更好,因为它没有使用核心动画。

    该方法还与useLayoutToLayoutNavigationTransitions 兼容,因此您可以获得所有不错的东西,例如将新导航项推送到导航栏等(不过我只在 iOS8 上测试过)。

    以下是我的步骤:

    1。有一个从一个 UICollectionViewController 到另一个 UICollectionViewController 的 layoutToLayout 过渡:


    DetailViewController *detail = [[DetailViewController alloc] init];
    detail.useLayoutToLayoutNavigationTransitions = YES;
    [self.navigationController pushViewController:detail animated:YES];
    

    ...UICollectionViewController 子类中的其他地方...

    - (UICollectionViewTransitionLayout *)collectionView:(UICollectionView *)collectionView transitionLayoutForOldLayout:(UICollectionViewLayout *)fromLayout newLayout:(UICollectionViewLayout *)toLayout
    {
        NSArray *supplementaryKinds = @[]; // optional supplementary view kinds
        TLTransitionLayout *layout = [[TLTransitionLayout alloc] initWithCurrentLayout:fromLayout nextLayout:toLayout supplementaryKinds:supplementaryKinds];
        return layout;
    }
    

    2。有一个 UINavigationControllerDelegate 在某处实现此方法:


    - (id<UIViewControllerAnimatedTransitioning>)navigationController:(UINavigationController *)navigationController
                                      animationControllerForOperation:(UINavigationControllerOperation)operation
                                                   fromViewController:(UIViewController*)fromVC
                                                     toViewController:(UIViewController*)toVC
    {
        if (operation == UINavigationControllerOperationPush) {
            return [[PushLayoutToLayoutAnimator alloc] init];
        }
    
        if (operation == UINavigationControllerOperationPop) {
            return [[PopLayoutToLayoutAnimator alloc] init];
        }
        
        return nil;
    }
    

    3。实现动画师:


    #import "TTProfileDetailPushAnimator.h"
    #import <TLTransitionLayout.h>
    
    @implementation TTProfileDetailPushAnimator
    
    - (NSTimeInterval)transitionDuration:(id <UIViewControllerContextTransitioning>)transitionContext
    {
        return 0.5;
    }
    
    - (void)animateTransition:(id<UIViewControllerContextTransitioning>)transitionContext
    {
        UICollectionViewController *toViewController;
        toViewController = (UICollectionViewController *)[transitionContext viewControllerForKey:UITransitionContextToViewControllerKey];
        NSAssert([toViewController isKindOfClass:[UICollectionViewController class]], @"must be collection view controller");
        NSAssert(toViewController.useLayoutToLayoutNavigationTransitions, @"expecting layoutToLayout transition!");
    
        [[transitionContext containerView] addSubview:toViewController.view];
    
        UICollectionViewLayout *toLayout = toViewController.collectionViewLayout;
        UICollectionView *toCollectionView = toViewController.collectionView;
        NSTimeInterval duration = [self transitionDuration:transitionContext];
        
        UICollectionViewLayoutInteractiveTransitionCompletion completionBlock = ^(BOOL completed, BOOL finished) {
            [transitionContext completeTransition:![transitionContext transitionWasCancelled]];
        };
    
        TLTransitionLayout *layout;
        layout = (TLTransitionLayout *)[toCollectionView transitionToCollectionViewLayout:toLayout
                                                                                 duration:duration
                                                                                   easing:CubicEaseInOut
                                                                               completion:completionBlock];
    
        CGPoint toOffset = [toCollectionView toContentOffsetForLayout:layout
                                                           indexPaths:[toCollectionView indexPathsForSelectedItems]
                                                            placement:TLTransitionLayoutIndexPathPlacementCenter];
        
        layout.toContentOffset = toOffset;
    }
    
    
    @end
    

    #import "TTProfileDetailPopAnimator.h"
    #import <TLTransitionLayout.h>
    
    @implementation TTProfileDetailPopAnimator
    
    - (NSTimeInterval)transitionDuration:(id <UIViewControllerContextTransitioning>)transitionContext
    {
        return 0.5;
    }
    
    - (void)animateTransition:(id<UIViewControllerContextTransitioning>)transitionContext
    {
        UICollectionViewController* toViewController;
        toViewController = (UICollectionViewController *)[transitionContext viewControllerForKey:UITransitionContextToViewControllerKey];
        UICollectionViewController* fromViewController;
        fromViewController = (UICollectionViewController *)[transitionContext viewControllerForKey:UITransitionContextFromViewControllerKey];
        
        NSAssert([toViewController isKindOfClass:[UICollectionViewController class]], @"toVC must be collection view controller");
        NSAssert([fromViewController isKindOfClass:[UICollectionViewController class]], @"fromVC must be collection view controller");
        NSAssert(fromViewController.useLayoutToLayoutNavigationTransitions, @"expecting layoutToLayout transition!");
    
        [[transitionContext containerView] insertSubview:toViewController.view aboveSubview:fromViewController.view];
        
        UICollectionViewLayout *toLayout = toViewController.collectionViewLayout;
        UICollectionView *toCollectionView = toViewController.collectionView;
        NSTimeInterval duration = [self transitionDuration:transitionContext];
        
        UICollectionViewLayoutInteractiveTransitionCompletion completionBlock = ^(BOOL completed, BOOL finished) {
            [transitionContext completeTransition:![transitionContext transitionWasCancelled]];
        };
        
        TLTransitionLayout *layout;
        layout = (TLTransitionLayout *)[toCollectionView transitionToCollectionViewLayout:toLayout
                                                                                 duration:duration
                                                                                   easing:CubicEaseInOut
                                                                               completion:completionBlock];
    
        CGPoint toOffset = [toCollectionView toContentOffsetForLayout:layout
                                                           indexPaths:[toCollectionView indexPathsForVisibleItems]
                                                            placement:TLTransitionLayoutIndexPathPlacementCenter];
        layout.toContentOffset = toOffset;
    }
    
    @end
    

    【讨论】:

    • 这似乎是一个很棒的解决方案。你有一个正在工作的项目吗?你还能对单元格的子视图使用自动布局吗?
    • @BobdeGraaf 是的,这在我的应用程序“Inkmonkey”itunes.apple.com/us/app/inkmonkey-the-tattoo-network/… 中工作(在用户个人资料屏幕中)。我的单元格包含 UIViewController 视图。
    • 我注意到了两个缺点:TLTransitionLayout 有时(非常罕见)由于某种原因而崩溃,我还不知道为什么。此外,添加一个大的视图层次结构(如 UIViewController 视图作为 UICollectionViewCell 的子视图)对于 UIKit 来说非常繁重,并且会使应用程序在旧设备上感觉非常迟钝。 Iphone6 和 6+ 处理得很好。
    • 是的,我也在使用自动布局
    • stefreak,使用您的确切代码,push animator 可以完美运行,但 pop 动画代码总是崩溃,知道为什么吗?你还说你使用自动布局。所以我假设你在某个地方为约束设置动画?你能指出我正确的方向(或提供一些代码)我需要在哪里为我的 collectionviewcell 的子视图的自动布局约束设置动画吗? :)
    猜你喜欢
    • 2016-05-22
    • 1970-01-01
    • 2017-01-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多