scrollViewWillEndDragging: withVelocity: targetContentOffset: no funciona en los bordes de un UIScrollView


Estoy tratando de implementar una barra de pestañas personalizada que se puede desplazar y tiene paginación en cada elemento de la barra de pestañas. Para eso estoy usando el delegado scrollViewWillEndDragging:withVelocity:targetContentOffset: que funciona perfectamente con un problema.

La forma en que funciona mi paginación es, si el contentOffset está cerca del elemento correcto, el targetContentOffset cambia al desplazamiento de ese elemento. Lo mismo para el lado izquierdo.

El problema es, cada vez que estoy en la mitad izquierda del primer elemento y la derecha de la última (la vista de desplazamiento funciona horizontalmente) se supone que debe ir a contentOffset 0 y el desplazamiento de contenido del elemento más a la derecha (menos los que están en la pantalla), pero no lo hace.

He comprobado con el depurador y el targetContentOffset->x es de hecho 0 (en el primer caso - a la izquierda del elemento más a la izquierda). Así que el problema es que UIScrollView no se desplaza allí. Estoy perdido.

Aquí está mi delegado implementado:

- (void)scrollViewWillEndDragging:(UIScrollView *)scrollView
                 withVelocity:(CGPoint)velocity
          targetContentOffset:(inout CGPoint *)targetContentOffset{
     NSInteger index = lrintf(targetContentOffset->x/self.tabWidth);
     targetContentOffset->x = index * self.tabWidth;
}

Aquí está el diagrama que explica lo que quiero hacer.

|-------|-------|-------|-------|-------|-------|-------|
|       |       |       |       |       |       |       |
|       |       |       |       |       |       |       |
|_______|_______|_______|_______|_______|_______|_______|

        |_______________________________________|
         where it is and i scroll it to the left

   <----|

   |_______________________________________|
              where it would stop

|_______________________________________|
        where i want it to stop
Author: dvieira, 2012-06-04

5 answers

Parece que este es un problema conocido. Después de algunas investigaciones y hablar con otras personas se sugirió que podría ser un error, que resultó ser correcto. Lo reporté a Apple y estaba marcado como duplicado, pero todavía está abierto. Solo respondo por aquellos de ustedes con el mismo problema. Lo soluciono como sugiere Big Papoo, usando un desplazamiento cercano a lo que quiero (0.1 parece hacerlo). Lo mismo para el extremo derecho.

 14
Author: dvieira,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-06-27 11:27:17

Problema solucionado en iOS 6.0.

Ahora funciona como debería.

 9
Author: Rany A. Ishak,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-10-10 13:08:19

Traté de establecer el desplazamiento final a algo ligeramente fuera de cero o el tamaño del contenido como sugirió Big Papoo, pero noté que esto elimina el rebote de desplazamiento excesivo. Mi solución a esto fue comprobar el targetContentOffset original para ver si es igual a cero o el contentSize y dejarlo si lo es:

- (void)scrollViewWillEndDragging:(UIScrollView *)scrollView withVelocity:(CGPoint)velocity targetContentOffset:(inout CGPoint *)targetContentOffset {

    float expectedOffset = targetContentOffset->x;
    if (expectedOffset == 0 || expectedOffset == scrollView.contentSize.width) return; // Scroll view will bounce so leave the targetContentOffset.

    float targetOffset = [self roundedOffset:expectedOffset]; // Round your offset.

    // Adjust the offset to make sure it works.
    if (targetOffset == 0) targetOffset = 1;
    else if (targetOffset == SCROLLVIEW_WIDTH) targetOffset = SCROLLVIEW_WIDTH - 1;

    targetContentOffset->x = targetOffset;
}

Por supuesto, puede usar scrollViewDidEndDecelerating: para mover el scrollview que 1 punto.

 8
Author: Adam Swinden,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-09-18 11:13:12

He encontrado 2 comportamientos indocumentados que usted puede investigar : - Ajuste cero como el desplazamiento final no funciona, sugiero poner 1 o algo mayor que cero (0.5 puede funcionar, no probado) - Será mejor que compruebe el signo de velocidad y calcular su desplazamiento final para estar en el lado izquierdo o derecho del punto actual donde el usuario eliminado es el dedo. No trate de hacer que el desplazamiento vaya hacia atrás en el otro lado.

 3
Author: Big Papoo,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-06-26 23:37:20

Si estás usando una vista de tabla horizontal, entonces dentro de tu función scrollViewWillEndDragging:withVelocity: targetContentOffset:, puedes llamar a:

[self.tableView scrollToRowAtIndexPath:[NSIndexPath indexPathForRow:<index> inSection:<section>] atScrollPosition:UITableViewScrollPositionTop animated:YES];

Encontré que esto funciona mucho mejor que tratar de manipular targetContentOffset->y en una vista de tabla horizontal.

 0
Author: Mr. T,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-08-09 00:36:47