ios - Limitación del movimiento vertical de UIAttachmentBehavior dentro de una UICollectionView
objective-c uikit-dynamics (6)
Tengo un UICollectionView
horizontal con un UICollectionViewFlowLayout
personalizado que tiene un UIAttachmentBehavior
establecido en cada celda para darle una sensación de rebote cuando se desplaza hacia la izquierda y hacia la derecha. El comportamiento tiene las siguientes propiedades:
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 posición también usando un UIAttachmentBehavior
. Naturalmente, rebota un poco hacia arriba y hacia abajo hasta que descansa en su posición. Todo está funcionando como se esperaba hasta ahora.
El problema que tengo comienza a aparecer 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. El agregado de la función de movimiento hacia la izquierda y hacia la derecha hacia arriba y hacia abajo que la celda ya tiene para ser agregado. Esto resulta en un movimiento circular muy extraño en la celda.
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 el uso de múltiples comportamientos de archivos adjuntos y la desactivación del desplazamiento en la vista de colección hasta que la celda recién agregada se haya detenido, pero ninguno de ellos parece detener esto.
¿Ha intentado eliminar manualmente las animaciones de las celdas con la CALayer
las CALayer
de removeAllAnimations
?
Así es como me las arreglé para hacerlo. El FloatRange limita el rango del archivo adjunto, por lo que si desea que se desplace hacia arriba y hacia abajo en la pantalla, simplemente establece números realmente grandes.
Esto va dentro de la función RecognPapPanGesture (remitente: 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)
He recurrido a desactivar el desplazamiento en la vista de colección durante un período de tiempo específico después de agregar una nueva celda, luego eliminar el comportamiento del archivo adjunto después de que ese tiempo haya pasado usando su propiedad de action
, y luego agregar un nuevo comportamiento de archivo adjunto de inmediato.
De esa manera, me aseguro de que la animación ascendente se detenga antes de que la vista de la colección se desplace hacia la izquierda o hacia la derecha, pero también el rebote hacia la izquierda / hacia la derecha todavía está allí cuando se desplaza.
Ciertamente no es la solución más elegante pero funciona.
Querrá eliminar el comportamiento cuando la vista de colección comience a desplazarse, o tal vez reducir considerablemente la elasticidad para que descanse sin problemas, pero de manera rápida. Si lo piensa, lo que está viendo es un movimiento realista para el comportamiento de apego que ha descrito.
Para mantener el rebote vertical a la misma velocidad pero evitar el rebote horizontal, deberá agregar otros comportamientos, como un comportamiento de colisión con límites a la izquierda y derecha de cada celda agregada. Esto aumentará un poco la complejidad de la física y puede afectar el rendimiento del desplazamiento, pero valdría la pena intentarlo.
Si está utilizando iOS 9 y superior, la función de deslizamiento dentro de la clase 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 efectivo para deslizar [documentación de Apple] 1
Una forma de resolver esto es usar la propiedad heredada .action del comportamiento del archivo adjunto.
Primero deberá configurar un par de variables, algo como (pasando de la memoria, código no probado):
BOOL limitVerticalMovement = TRUE;
CGFloat staticCenterY = CGRectGetHeight(self.collectionView.frame) / 2;
Establézcalos como propiedades de su UICollectionViewFlowLayout personalizado
Cuando creas tu comportamiento de apego:
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 función de limitación configurando limitVerticalMovement según corresponda.