Limitar el movimiento vertical de UIAttachmentBehavior dentro de UICollectionView

Tengo un UICollectionView horizontal con un UICollectionViewFlowLayout personalizado que tiene un set UIAttachmentBehavior en cada celda para darle una sensación de saltos cuando se desplaza hacia la izquierda y hacia la derecha. El comportamiento tiene las siguientes properties:

 attachmentBehavior.length = 1.0f; attachmentBehavior.damping = 0.5f; attachmentBehavior.frequency = 1.9f; 

Cuando se agrega una nueva celda a la vista de colección, se agrega en la parte inferior y luego se anima a su position también usando un UIAttachmentBehavior . Naturalmente, rebota hacia arriba y hacia abajo un poco hasta que descanse en su position. Todo funciona como se espera hasta ahora.

introduzca la descripción de la imagen aquí

El problema que comienzo a aparecer aparece cuando la vista de colección se desplaza hacia la izquierda o hacia la derecha antes de que la celda recién agregada se detenga. Agrega bounciness hacia la izquierda y hacia la derecha hacia arriba y hacia abajo, ya que la célula ya debe agregarse. Esto resulta en un movimiento circular muy extraño en la celda.

introduzca la descripción de la imagen aquí

Mi pregunta es: ¿es posible detener el movimiento vertical de un UIAttachmentBehavior mientras se desplaza la vista de colección? He intentado diferentes enfoques como usar múltiples comportamientos de connection y deshabilitar el desplazamiento en la vista de colección hasta que la célula recién agregada se haya apagado, pero ninguno de ellos parece detenerlo.

Una forma de resolver esto es usar la propiedad .action henetworkingada del comportamiento del file adjunto.

Deberá configurar un par de variables primero, algo así como (pasando de memory, código no comprobado):

 BOOL limitVerticalMovement = TRUE; CGFloat staticCenterY = CGRectGetHeight(self.collectionView.frame) / 2; 

Establezca estas como properties de su UICollectionViewFlowLayout personalizado

Cuando creas tu comportamiento de datos adjuntos:

 UIAttachmentBehavior *attachment = [[UIAttachmentBehavior alloc] initWithItem:item attachedToAnchor:center]; attachment.damping = 1.0f; attachment.frequency = 1.5f; attachment.action = ^{ if (!limitVerticalMovement) return; CGPoint center = item.center; center.y = staticCenterY; item.center = center; }; 

Luego puede activar y desactivar la function limitante estableciendo limitVerticalMovement según corresponda.

¿Has intentado eliminar manualmente las animaciones de las celdas con CALayer de removeAllAnimations ?

Deseará eliminar el comportamiento cuando la vista de colección comience a desplazarse, o quizás networkinguzca en gran medida la elasticidad para que se repose suavemente, pero rápidamente. Si lo piensas bien, lo que estás viendo es un movimiento realist para el comportamiento de apego que has descrito.

Para mantener el rebote vertical a la misma velocidad pero evitar el rebote horizontal, necesitaría agregar otros comportamientos, como un comportamiento de colisión con los límites a la izquierda y a la derecha de cada celda agregada. Esto boostá un poco la complejidad de la física y puede afectar el performance del desplazamiento, pero valdría la pena intentarlo.

He recurrido a deshabilitar el desplazamiento en la vista de colección durante un período de time específico después de agregar una nueva celda, luego de eliminar el comportamiento de los datos adjuntos después de que el time haya pasado usando su propiedad de action , y luego agregar nuevamente un comportamiento de datos adjuntos de inmediato.

De esta manera, me aseguro de que la animation ascendente se detenga antes de que la vista de colección se desplace hacia la izquierda o hacia la derecha, pero también el bouncy izquierdo / derecho sigue estando presente cuando se desplaza.

Ciertamente, no es la solución más elegante, pero funciona.

Si está utilizando iOS 9 y superior, entonces la function deslizante dentro de la class de adjuntos funcionará perfectamente para ese trabajo:

 class func slidingAttachmentWithItem(_ item: UIDynamicItem, attachmentAnchor point: CGPoint, axisOfTranslation axis: CGVector) -> Self 

se puede usar fácilmente y es muy eficaz para deslizar [documentation de Apple] 1

Así es como logré hacerlo. El FloatRange limita el scope del file adjunto, así que si quieres que vaya todo el path hacia arriba y hacia abajo de la pantalla, simplemente establecerás numbers realmente grandes.

Esto va dentro de func recognizePanGesture (emisor: UIPanGestureRecognizer) {}

 let location = sender.location(in: yourView.superview) var direction = "Y" var center = CGPoint(x: 0, y: 0) if self.direction == "Y" {center.y = 1} if self.direction == "X" {center.x = 1} let sliding = UIAttachmentBehavior.slidingAttachment(with: youView, attachmentAnchor: location, axisOfTranslation: CGVector(dx: center.x, dy: center.y)) sliding.attachmentRange = UIFloatRange(minimum: -2000, maximum: 2000) animator = UIDynamicAnimator(referenceView: self.superview!) animator.addBehavior(sliding)