对于UICollectionView selectItemAtIndexPath动画时间:动画:的scrollPosition:

问题描述 投票:35回答:7

我曾试图设定的时间(与正常的方法,我会尝试),用于设置UICollectionView的selectItemAtIndexPath:animated:scrollPosition:方法动画的持续时间(或scrollToItemAtIndexPath:atScrollPosition:animated:方法)。我试过[UIView setAnimationDuration],我尝试了在CATransaction加以包装。 (虽然我承认我可以在这个逻辑已经犯了一个错误),我已经成功了这一点,在改变该动画的持续时间。

思考?

更新:

我在这里尝试了好多种方法。最接近的解决方案是做什么,我们通常会为UIScrollView动画做的(通过设置动画:参数NO并在UIView动画块包装它)。这为滚动视图工作完全正常。然而,这种螺丝由于某种原因,UICollectionView创建过程。

我已经包含下面使用两种方法的例子。每种方法假定您有4个部分,在每个部分4项。此外,动画假设您正在从0,0到3,3。

使用默认的动画

部分的问题在这里肯定似乎绑UICollectionView。如果你采取以下方法(使用默认的动画选项) - 所有工作正常:

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

当该正在执行,在其之间的当前可见的细胞和目的小区的每个小区被创建。我已经包括登录的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]

使用自定义动画

当在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");
}];

当前可见的细胞消失,只有创建目的地之一。我已经包括在collectionView:cellForItemAtIndexPath:方法相同的日志记录:

Transition
Cell Created for Index Path: <NSIndexPath 0x71702f0> 2 indexes [3, 3]
Completed
iphone core-animation uicollectionview
7个回答
5
投票

我曾与我通过下面的代码解决UITableView类似的问题:

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

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

[CATransaction commit];

很显然,你不能animated:NO调用它,因为该方法里面的动画代码是很重要的。使用CATransaction包装为我工作的动画。


1
投票

对我来说,这个工程。显然,这需要一些调整(有更精确的时间,并使其滚动逆转,从底部到顶部。现在它仅支持垂直滚动从上到下)

调用是这样的:

[self scrollToIndexPath:[NSIndexPath indexPathForItem:40 inSection:0] withAnimationDuration:3.0f];

这里是代码

-(void)scrollToIndexPath:(NSIndexPath *)path withAnimationDuration:(float)duration
{
    NSIndexPath *firstCell = [[self.collectionView indexPathsForVisibleItems] objectAtIndex:0];
    UICollectionViewLayoutAttributes *attributesForFirstCell = [self.collectionView layoutAttributesForItemAtIndexPath:firstCell];
    CGRect firstCellRect = attributesForFirstCell.frame;
    CGPoint startPoint = firstCellRect.origin;

    NSIndexPath *destinationCell = path;
    UICollectionViewLayoutAttributes *attributesForDestCell = [self.collectionView layoutAttributesForItemAtIndexPath:destinationCell];
    CGRect destCellRect = attributesForDestCell.frame;
    CGPoint destPoint = destCellRect.origin;

    self.destination = destPoint;

    float delta = destPoint.y - startPoint.y;

    float cycle = (delta / (50*duration));
    self.pass = (int)cycle + 1;

    self.myTimer = [NSTimer scheduledTimerWithTimeInterval:0.02 target:self selector:@selector(scrollView) userInfo:nil repeats:YES];
}



- (void) scrollView {

    float w = self.pass;

    CGPoint scrollPoint = self.collectionView.contentOffset;
    scrollPoint.y = scrollPoint.y + w;

    if (scrollPoint.y >= self.destination.y)
        [self.myTimer invalidate];
    [self.collectionView setContentOffset: scrollPoint animated: NO];
}

0
投票

如果你把一些代码在scrollViewDidScroll:

我有致电selectItemAtIndexPath:animated:scrollPosition,然后使用scrollViewDidScroll:跑什么,我通常会在完成块运行解决了类似的问题。

当然,你可能会需要保持一个或两个BOOL的轨道据此决定是否需要执行的scrollViewDidScroll:什么。


0
投票

你可以用AnimationEngine库干净做到这一点。它包装在基于块的动画语法CADisplayLink。我张贴与动画here一个代码示例答案contentOffset。您需要做的仅仅从indexPath到contentOffset转换。


0
投票

我能得到它的工作与动画假包装这里面UIView.animate:

UIView.animate(withDuration: 0.7, delay: 0.0, options: .curveEaseInOut, animations: {
            self.collectionView.scrollToItem(at: IndexPath(row: 0, section: 0), at: .centeredHorizontally, animated: false)
        }, completion: nil)

-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);
}

-3
投票

实际的解决办法是,你需要做到这一点scrollToItemAtIndexPath在主队列。所以,只有你能得到它的实际工作。

示例代码:

 dispatch_async(dispatch_get_main_queue(), ^{

    [collectionView scrollToItemAtIndexPath:indexPath atScrollPosition:UICollectionViewScrollPositionCenteredHorizontally animated:NO];

});

© www.soinside.com 2019 - 2024. All rights reserved.