使用iOS 7 API进行UICollectionView交互式布局转换

时间:2013-09-25 14:53:44

标签: iphone ios cocoa-touch uicollectionview uicollectionviewlayout

我正在尝试处理新的iOS 7 API,它允许交互式动画视图控制器转换,包括UICollectionViewLayout之间的转换。

我已经从WWDC 2013中采集并修改了示例代码,“iOS-CollectionViewTransition”,可在此处找到:https://github.com/timarnold/UICollectionView-Transition-Demo

原始演示在我找到它时未处于工作状态,可以通过Apple Developer帐户访问,在此处:https://developer.apple.com/downloads/index.action?name=WWDC%202013

我的应用版本提供了一个包含两个布局的集合视图,这两个布局都具有不同属性的UICollectionViewFlowLayout布局。

在第一个布局中点击一个单元格正确地设置为第二个,包括,重要的是,在新布局中滚动到的项目。起初,我对新集合视图如何知道设置其内容偏移以使适当的单元格可见感到困惑,但我了解到它基于呈现集合视图的selected属性执行此操作。

捏住第一个布局中的项目时,应使用UICollectionViewTransitionLayoutUIViewControllerAnimatedTransitioningUIViewControllerInteractiveTransitioning为新布局设置动画效果。这样可行,但是在新布局或转换布局中,压缩单元格滚动到。

我已经尝试在不同位置设置压缩单元格上的selected属性(试图模仿点击某个项目时所描述的行为以推动新的视图控制器),但无济于事。“ / p>

有关如何解决此问题的任何想法?

2 个答案:

答案 0 :(得分:19)

您可以在转换过程中自己操纵contentOffset,这实际上比UICollectionView's内置动画更精细控制。

例如,您可以像这样定义过渡布局,以在“到”和“从”偏移之间进行插值。你只需要根据你想要的结果来计算“to”自己的偏差:

@interface MyTransitionLayout : UICollectionViewTransitionLayout
@property (nonatomic) CGPoint fromContentOffset;
@property (nonatomic) CGPoint toContentOffset;
@end

#import "MyTransitionLayout.h"
@implementation MyTransitionLayout

- (void) setTransitionProgress:(CGFloat)transitionProgress
{
    super.transitionProgress = transitionProgress;
    CGFloat f = 1 - transitionProgress;
    CGFloat t = transitionProgress;
    CGPoint offset = CGPointMake(f * self.fromContentOffset.x + t * self.toContentOffset.x, f * self.fromContentOffset.y + t * self.toContentOffset.y);
    self.collectionView.contentOffset = offset;
}

@end

需要注意的一点是,当转换完成时,contentOffset将重置为“from”值,但您可以通过将其设置回{的完成块中的“to”偏移来否定它。 {1}}

startInteractiveTransitionToCollectionViewLayout

<强>更新

我在新的GitHub库TLLayoutTransitioning中发布了此实现和一个工作示例。该示例是非交互式的,旨在演示CGPoint toContentOffset = ...; [self.collectionViewController.collectionView startInteractiveTransitionToCollectionViewLayout:layout completion:^(BOOL completed, BOOL finish) { if (finish) { self.collectionView.contentOffset = toContentOffset; } }]; 上的改进动画,但它使用了与上述技术相结合的交互式转换API。请查看TLTransitionLayout class并尝试在示例工作区中运行"Resize" example

也许setCollectionViewLayout:animated:completion可以完成您的需要。

更新2

我在TLLayoutTransitioning库中添加了一个交互式示例。尝试在Examples工作区中运行"Pinch" example。这个将可见细胞作为一组捏住。我正在研究另一个压缩单个单元格的示例,以便在转换过程中单元格跟随您的手指,而其他单元格遵循默认的线性路径。

更新3

我最近添加了更多内容偏移位置选项:最小,中心,顶部,左侧,底部和右侧。 TLTransitionLayout现在支持30多个宽松功能,由Warren Moore AHEasing library提供。

答案 1 :(得分:1)

谢谢Timothy Moose。它也适用于 iOS14。我没有尝试通过手指进行交互,但是对于更改列表布局上的网格布局的简单动画,它工作正常。可以替换

self.collectionView?.contentOffset = ...

setContentOffset(_ contentOffset: yourOffset, animated: false)

如果你不这样做,内容会在动画过程中反弹一点。

这是我在 Swift 中的示例:

final class SFDocumentsManagerTransitionLayout: UICollectionViewTransitionLayout {
    var fromContentOffset: CGFloat = 0
    var toContentOffset: CGFloat = 0
    
    override var transitionProgress: CGFloat {
        didSet {
            let f = 1 - self.transitionProgress
            let t = self.transitionProgress
            self.collectionView?.setContentOffset(CGPoint(x: 0,
                                                          y: f * self.fromContentOffset + t * self.toContentOffset),
                                                  animated: false)
        }
    }
}