UICollectionView的动画持续时间selectItemAtIndexPath:animated:scrollPosition:

dtu*_*net 36 iphone core-animation uicollectionview

我试图设置持续时间(使用我将尝试的常规方法)来设置UICollectionView的selectItemAtIndexPath:animated:scrollPosition:方法(或scrollToItemAtIndexPath:atScrollPosition:animated:方法)的动画持续时间.我试过了[UIView setAnimationDuration],我试过将它包装成一个CATransaction.在改变动画持续时间方面,我一直没有成功(尽管我承认我可能在这个逻辑中犯了一个错误).

思考?

更新:

我在这里尝试了很多方法.最接近的解决方案是执行我们通常对UIScrollView动画执行的操作(通过将animated:参数设置为NO并将其包装在UIView动画块中).这适用于scrollview.但是,这个螺丝与UICollectionView创作过程有某些原因.

我在下面使用两种方法包含了一个示例.每种方法都假设您有4个部分,每个部分有4个项目.此外,动画假设您从0,0移动到3,3.

使用默认动画

这里的部分问题肯定与此有关UICollectionView.如果您采用以下方法(使用默认动画选项) - 一切正常:

[self.collectionView scrollToItemAtIndexPath:[NSIndexPath indexPathForItem:3 inSection:3]
                                atScrollPosition:UICollectionViewScrollPositionCenteredHorizontally
                                        animated:YES];
Run Code Online (Sandbox Code Playgroud)

执行此操作时,将创建当前可见单元格与目标单元格之间的每个单元格.我已经包含了登录collectionView:cellForItemAtIndexPath:方法:

2013-05-18 09:33:24.366 DEF-CV-Testing[75463:c07] Transition
Cell Created for Index Path: <NSIndexPath 0x8913f40> 2 indexes [0, 1]
Cell Created for Index Path: <NSIndexPath 0x75112e0> 2 indexes [0, 2]
Cell Created for Index Path: <NSIndexPath 0xfe1a6c0> 2 indexes [0, 3]
Cell Created for Index Path: <NSIndexPath 0x89159e0> 2 indexes [1, 0]
Cell Created for Index Path: <NSIndexPath 0x8a10e70> 2 indexes [1, 1]
Cell Created for Index Path: <NSIndexPath 0x7510d90> 2 indexes [1, 2]
Cell Created for Index Path: <NSIndexPath 0x75112a0> 2 indexes [1, 3]
Cell Created for Index Path: <NSIndexPath 0x8915a00> 2 indexes [2, 0]
Cell Created for Index Path: <NSIndexPath 0x75111c0> 2 indexes [2, 1]
Cell Created for Index Path: <NSIndexPath 0xfe17f30> 2 indexes [2, 2]
Cell Created for Index Path: <NSIndexPath 0xfe190c0> 2 indexes [2, 3]
Cell Created for Index Path: <NSIndexPath 0xfe16920> 2 indexes [3, 0]
Cell Created for Index Path: <NSIndexPath 0x75112a0> 2 indexes [3, 1]
Cell Created for Index Path: <NSIndexPath 0xfe1a4f0> 2 indexes [3, 2]
Cell Created for Index Path: <NSIndexPath 0x75142d0> 2 indexes [3, 3]
Run Code Online (Sandbox Code Playgroud)

使用自定义动画

scrollToItemAtIndexPath:方法包装在UIView动画块中时,无法正确创建项目.请参阅此处的代码示例

[UIView animateWithDuration:5.0 delay:0.0 options:0 animations:^{
    [self.collectionView scrollToItemAtIndexPath:[NSIndexPath indexPathForItem:3 inSection:3]
                                atScrollPosition:UICollectionViewScrollPositionCenteredHorizontally
                                        animated:NO];
} completion:^(BOOL finished) {
    NSLog(@"Completed");
}];
Run Code Online (Sandbox Code Playgroud)

当前可见的单元格消失,仅创建目标单元格.我在collectionView:cellForItemAtIndexPath:方法中包含了相同的日志记录:

Transition
Cell Created for Index Path: <NSIndexPath 0x71702f0> 2 indexes [3, 3]
Completed
Run Code Online (Sandbox Code Playgroud)

Sul*_*han 7

我遇到了类似的问题UITableView,我通过以下代码解决了这个问题:

[CATransaction begin];
[CATransaction setCompletionBlock:onCompletion];
[CATransaction setAnimationDuration:duration];

[self.collectionView scrollToItemAtIndexPath:[NSIndexPath indexPathForItem:3 inSection:3]
                            atScrollPosition:UICollectionViewScrollPositionCenteredHorizontally
                                    animated:YES];

[CATransaction commit];
Run Code Online (Sandbox Code Playgroud)

显然,你无法调用它,animated:NO因为方法中的动画代码很重要.使用a CATransaction包装动画为我工作.

  • 不幸的是,没有 - 这不起作用.在这种情况下,动画确实发生 - 但是在预定义的持续时间(不是在`setAnimationDuration:`方法中设置的持续时间). (8认同)

Kal*_*Kal -1

我找到了一种手动滚动并完全绕过self.collectionView scrollToItemAtIndexPath..

我还尝试使用完成块来循环不同的部分,但这导致了不稳定的体验。

请注意,此示例是垂直滚动的——您应该能够将其更改为水平滚动。您可能还需要调整偏移量,以便滚动停止在所需的位置。同样,令我惊讶的是 API 没有提供控制速度的方法。

-(void)scrollMethod {

    // Find the point where scrolling should stop.
    UICollectionViewLayoutAttributes *attr = [self.collectionView layoutAttributesForItemAtIndexPath:[NSIndexPath indexPathForItem:3 inSection:3]];

    CGRect cellRect = attr.frame;

    self.source = self.collectionView.frame.origin;
    self.destination = cellRect.origin;
    self.myTimer = [NSTimer scheduledTimerWithTimeInterval:0.001 target:self selector:@selector(scrollOn) userInfo:nil repeats:YES];

}

-(void)scrollOn {
    self.collectionView.contentOffset = self.source;
    // If we have crossed where we need to be, quit the timer
    if ( self.source.y > self.destination.y)
        [self.myTimer invalidate];

    self.source = CGPointMake(self.source.x, self.source.y+1);
}
Run Code Online (Sandbox Code Playgroud)

  • @Lifely 如果您确实提出了一些有用的建议而不是投反对票和发表冷嘲热讽,这可能会有所帮助。上述解决方案确实有效,而且我还活着:-) (4认同)