Pregunta Duración de la animación para UICollectionView selectItemAtIndexPath: animated: scrollPosition:


Intenté establecer la duración (con los métodos normales que probaría) para configurar la duración de la animación para UICollectionView selectItemAtIndexPath:animated:scrollPosition: método (o el scrollToItemAtIndexPath:atScrollPosition:animated: método). He intentado [UIView setAnimationDuration], y he tratado de envolverlo en una CATransaction. Hasta ahora no he tenido éxito en cambiar esa duración de la animación (aunque admito que podría haber cometido un error en esta lógica).

¿Pensamientos?

ACTUALIZAR: 

He intentado una buena cantidad de enfoques aquí. La solución más cercana es hacer lo que normalmente haríamos por UIScrollView animación (configurando el argumento animado: NO y envolviéndolo en una UIView bloque de animación). Esto funciona perfectamente bien para scrollview. Sin embargo, esto se atornilla con el UICollectionView proceso de creación por alguna razón.

He incluido un ejemplo a continuación utilizando dos enfoques. Cada enfoque asume que tiene 4 secciones con 4 elementos en cada sección. Además, la animación asume que se está moviendo de 0,0 a 3,3.

Usando la animación predeterminada

Parte del problema aquí ciertamente parece estar ligado a UICollectionView. Si toma el siguiente enfoque (utilizando la opción de animación predeterminada), todo funciona bien:

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

Cuando esto se ejecuta, se crean cada celda entre las celdas visibles actuales y la celda de destino. He incluido el inicio de sesión en el collectionView:cellForItemAtIndexPath: método:

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]

Usando animación personalizada

Al envolver el scrollToItemAtIndexPath: método en una UIView bloque de animación, los elementos no se crean correctamente. Vea el ejemplo del código aquí:

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

Las celdas actualmente visibles desaparecen y solo se crea el destino. He incluido la misma sesión en el collectionView:cellForItemAtIndexPath: método:

Transition
Cell Created for Index Path: <NSIndexPath 0x71702f0> 2 indexes [3, 3]
Completed

32
2018-05-16 20:58


origen


Respuestas:


Tuve problemas similares con UITableView que resolví con el siguiente código:

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

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

[CATransaction commit];

Obviamente, no puedes llamarlo con animated:NO porque el código de animación dentro del método es importante. Usando un CATransaction para envolver la animación funcionó para mí.


5
2018-05-22 13:56



Para mí esto funciona Obviamente necesita algunos ajustes (para tener un tiempo más preciso y para hacer que se desplace hacia atrás, de abajo hacia arriba. Ahora solo admite el desplazamiento vertical de arriba a abajo)

Llame a algo como esto:

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

y aquí está el código

-(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
2018-05-25 18:35



¿Qué pasa si pones un código en scrollViewDidScroll: ?

Tengo un problema similar que resolví llamando selectItemAtIndexPath:animated:scrollPosition y luego usando scrollViewDidScroll: para ejecutar lo que normalmente correría en un bloque de finalización.

Por supuesto, probablemente tendrá que hacer un seguimiento de un BOOL o dos para decidir si necesita ejecutar algo en scrollViewDidScroll:.


0
2017-07-23 11:46



Puedes hacer esto limpiamente con el AnimationEngine biblioteca. Envuelve un CADisplayLink en sintaxis de animación basada en bloques. Publiqué una respuesta aquí con un ejemplo de código que anima contentOffset. Solo necesita hacer la conversión de indexPath a contentOffset.


0
2018-06-25 22:37



Encontré una forma de desplazarme manualmente y omitir por completo self.collectionView scrollToItemAtIndexPath ..

También traté de usar el bloque de finalización para recorrer las diferentes secciones, pero esto resultó en una experiencia desigual.

Tenga en cuenta que este ejemplo se desplaza verticalmente; debería poder cambiarlo para desplazarse horizontalmente. Probablemente también deba ajustar los desplazamientos para que el desplazamiento se detenga en la ubicación deseada. De nuevo, me sorprende que la API no ofrezca una forma de controlar la velocidad.

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

-1
2018-05-20 17:33



La solución real es que necesita hacer esto scrollToItemAtIndexPath en la cola principal. para que solo usted pueda obtener el funcionamiento real de la misma.

Código de ejemplo:

 dispatch_async(dispatch_get_main_queue(), ^{

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

});


-2
2018-02-10 05:51