10

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

我已经从 WWDC 2013 “iOS-CollectionViewTransition”中获取并修改了示例代码,可以在这里找到:https ://github.com/timarnold/UICollectionView-Transition-Demo

原来的demo,我发现它的时候还没有工作,可以用苹果开发者账号访问,这里:https ://developer.apple.com/downloads/index.action?name=WWDC%202013

我的应用程序版本展示了一个包含两种布局的集合视图,两种布局都UICollectionViewFlowLayout具有不同的属性。

在第一个布局中点击一个单元格会正确地动画到第二个,包括,关键的是,在新布局中滚动到的点击项目。起初我对新的集合视图如何知道设置其内容偏移量以便适当的单元格可见感到困惑,但我了解到它是基于selected呈现集合视图的属性来做到这一点的。

捏住第一个布局中的项目也应该使用UICollectionViewTransitionLayout,UIViewControllerAnimatedTransitioningUIViewControllerInteractiveTransitioning, 为新布局设置动画。这可行,但在新布局或过渡布局中不会滚动到捏合单元格。

我尝试selected在不同位置的捏合单元格上设置属性(以尝试模仿在点击项目以推动新视图控制器时描述的行为),但无济于事。

关于如何解决这个问题的任何想法?

4

2 回答 2

19

您可以在过渡期间操纵自己,这实际上为您提供了比内置动画contentOffset更细粒度的控制。UICollectionView's

例如,您可以像这样定义过渡布局,以在“to”和“from”偏移之间进行插值。您只需要根据您希望事情的结果来计算“到”偏移量:

@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”偏移量来否定它startInteractiveTransitionToCollectionViewLayout

CGPoint toContentOffset = ...;
[self.collectionViewController.collectionView startInteractiveTransitionToCollectionViewLayout:layout completion:^(BOOL completed, BOOL finish) {
    if (finish) {
        self.collectionView.contentOffset = toContentOffset;
    }
}];

更新

我在新的 GitHub 库TLLayoutTransitioning中发布了这个实现和一个工作示例。该示例是非交互式的,旨在演示改进的动画效果setCollectionViewLayout:animated:completion,但它利用了与上述技术相结合的交互式过渡 API。查看TLTransitionLayout该类并尝试在示例工作区中运行“调整大小”示例

也许TLTransitionLayout可以完成你所需要的。

更新 2

我在 TLLayoutTransitioning 库中添加了一个交互式示例。尝试在示例工作区中运行“Pinch”示例。这个将可见细胞捏成一组。我正在研究另一个示例,该示例会捏住单个单元格,使单元格在过渡期间跟随您的手指,而其他单元格遵循默认的线性路径。

更新 3

我最近添加了更多内容偏移放置选项:最小、中心、顶部、左侧、底部和右侧。transitionToCollectionViewLayout:现在支持 Warren Moore 的 AHEasing 库提供的 30 多种缓动函数

于 2013-10-08T20:43:54.387 回答
1

谢谢蒂莫西·穆斯。它也适用于 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)
        }
    }
}
于 2021-06-10T21:55:27.027 回答