Combining UIAttachmentBehavior and UICollisionBehavior
Using UIKit Dynamics I want to combine the UIAttachmentBehavior and the UICollisionBehavior in such a way that the user can drag the view around (using UIPanGestureRecognizer
) but not leave a specific area.
The problem arises when the user / UIView encounters the bounds of the collision behavior, since then no perpendicular movement is possible.
those. on collision with the left side of the border of the area, one "gets stuck" there and cannot move up or down, just right. Dragging the UIView back to the exact path used to work works.
Any help that UIDynamicItemBehavior is running on is greatly appreciated (tried elasticity, friction and resistance but no success).
source to share
I think you have implemented UIPanGestureRecognizer
incorrectly. Try the following example. Just create a new project and paste this code into your ViewController. If you need to reduce the dragging area, you can play with the function dragView
.
import UIKit
class ViewController: UIViewController, UICollisionBehaviorDelegate {
var collision: UICollisionBehavior!
var animator: UIDynamicAnimator!
override func viewDidLoad() {
super.viewDidLoad()
let container = UIView(frame: CGRect(x: 30, y: 60, width: 300, height: 500))
self.view.addSubview(container)
container.backgroundColor = .gray
self.animator = UIDynamicAnimator(referenceView: container);
//self.animator.setValue(true, forKey: "debugEnabled")
let greenBox = UIView(frame: CGRect(x: 60, y: 240, width: 50, height: 50))
greenBox.backgroundColor = .green
container.addSubview(greenBox)
let blueBox = UIView(frame: CGRect(x: 10, y: 10, width: 50, height: 50))
blueBox.backgroundColor = .blue
container.addSubview(blueBox)
let redBox = UIView(frame: CGRect(x: 200, y: 300, width: 50, height: 50))
redBox.backgroundColor = .red
container.addSubview(redBox)
self.collision = UICollisionBehavior(items: [greenBox, blueBox, redBox])
self.collision.translatesReferenceBoundsIntoBoundary = true
self.collision.collisionMode = .everything
self.animator.addBehavior(self.collision)
self.collision.collisionDelegate = self
let c = UIDynamicItemBehavior(items: [redBox])
c.density = 10000
self.animator.addBehavior(c)
let noRotation = UIDynamicItemBehavior(items: [greenBox, blueBox])
noRotation.allowsRotation = false
self.animator.addBehavior(noRotation)
let panGesture = UIPanGestureRecognizer(target: self, action: #selector(self.dragView(_:)))
greenBox.isUserInteractionEnabled = true
greenBox.addGestureRecognizer(panGesture)
let panGesture2 = UIPanGestureRecognizer(target: self, action: #selector(self.dragView(_:)))
blueBox.isUserInteractionEnabled = true
blueBox.addGestureRecognizer(panGesture2)
}
@objc func dragView(_ sender:UIPanGestureRecognizer){
if let viewDrag = sender.view {
self.view.bringSubview(toFront: viewDrag)
let translation = sender.translation(in: self.view)
viewDrag.center = CGPoint(x: viewDrag.center.x + translation.x, y: viewDrag.center.y + translation.y)
sender.setTranslation(CGPoint.zero, in: self.view)
animator.updateItem(usingCurrentState: viewDrag)
}
}
}
source to share