swift - 正确转换 UICollectionViewCell 中的 subview

标签 swift uicollectionview uicollectionviewcell

我正在使用 layoutToLayout 导航转换 (useLayoutToLayoutNavigationTransitions),但动画不流畅;单元格的 subview 在转换期间奇怪地跳跃:

enter image description here

可能是哪里出了问题?

我的 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;
            }
        }
    }
}

最佳答案

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

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

所以这些是我的步骤:

1。有从一个 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

关于swift - 正确转换 UICollectionViewCell 中的 subview ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26985312/

相关文章:

arrays - 对如何使用变异感到困惑

swift - 使用不存在的类型扩展测量单元的最佳方法?

ios - 全屏水平滚动 UICollectionView 单元格在第一个显示的 UIViewController 中使用时向下移动

iphone - uicollection View 可重用单元格图像在滚动时重新加载

ios - 将 UILabel 添加到图像

swift - 可选类型 'Int?' 的值未展开;您是要使用 '!' 还是 '?' ?

ios - UIMenuController 未在 UICollectionViewController 子类上显示自定义操作

ios - UICollectionview 和 Image loading 导致内存不足

ios - 从 UICollectionViewCell 使用 UICollectionView

ios - 双击CollectionViewCell时如何进行事件?