Reputation: 27
I would like to create a square in swift that starts at the top of the screen and fall down to the bottom of the screen and stay there. I also would like to be able to drag it with my finger toward the top and make it fall toward the bottom of the screen again. Any tips on how to do that?
I was able to create a square that falls toward the bottom of the screen already. I was also able to move it with my finger as well. But the problem is, whenever I move it, the square just stay in the same place. Gravity/collision/elasticity don't seem to work after I move it. I want it to fall after I lift my finger off the square. See below for an excerpt of my code. There is probably something simple that I miss. Any tips would be appreciated.
import UIKit
class ViewController: UIViewController {
var greenSquare: UIView?
var redSquare:UIView?
var animator: UIDynamicAnimator?
override func viewDidLoad() {
super.viewDidLoad()
createFallingObject()
func createFallingObject() {
//remove square from superview
redSquare?.removeFromSuperview()
//create the shape
var dimen = CGRect(x: 130,y: 25,width: 90,height: 90)
redSquare = UIView(frame: dimen)
redSquare?.backgroundColor = UIColor.red
//then add to the screen
self.view.addSubview(redSquare!)
//Initialize the animator
animator = UIDynamicAnimator(referenceView: self.view)
//Add gravity to the squares
let gravity = UIGravityBehavior(items: [redSquare!])
let direction = CGVector(dx: 0.0, dy: 0.05)
gravity.gravityDirection = direction
//Collision
let boundaries = UICollisionBehavior(items: [redSquare!])
boundaries.translatesReferenceBoundsIntoBoundary = true
//Elasticity
let bounce = UIDynamicItemBehavior(items: [redSquare!])
bounce.elasticity = 0.3
// 1. create a gesture recognizer (tap gesture)
let tapGesture = UITapGestureRecognizer(target: self, action: #selector(handleTap(sender:)))
//add pan gesture Regcognizer to the red square
let panGestureRecognizer = UIPanGestureRecognizer(target: self, action: #selector(handlePan))
redSquare?.addGestureRecognizer(panGestureRecognizer)
animator?.addBehavior(boundaries)
animator?.addBehavior(bounce)
animator?.addBehavior(gravity)
}
//this method handle pan
func handlePan(_ gestureRecognizer: UIPanGestureRecognizer) {
if gestureRecognizer.state == .began || gestureRecognizer.state == .changed {
let translation = gestureRecognizer.translation(in: self.view)
// note: 'view' is optional and need to be unwrapped
gestureRecognizer.view!.center = CGPoint(x: gestureRecognizer.view!.center.x + translation.x, y: gestureRecognizer.view!.center.y + translation.y)
gestureRecognizer.setTranslation(CGPoint.zero, in: self.view)
//redSquare?.frame.origin.x = translation.x
//redSquare?.frame.origin.y = translation.y
}
}
// 3. this method is called when a tap is recognized
func handleTap(sender: UITapGestureRecognizer) {
createFallingObject()
}
}
Upvotes: 1
Views: 1050
Reputation: 27
animator?.removeAllBehavior()
did the trick in the pan gesture routine
Upvotes: 0
Reputation: 15331
You should remove the item from the UIDynamicAnimator
when the pan gesture begin and add it back when it ends.
When a view is added to a dynamic animator its position should be determine by the animator and the animator alone. Removing the item from the animator will allow the view to position normally using its frame. Adding it back to the animator will cause the animator to resume positioning it from its current state.
Alternatively, if you need to the update the position of an item manually (i.e. not based on the physics of the animator), you should call animator.updateItem(usingCurrentState: myDynamicItem)
, where myDynamicItem
is the item you want to update.
Upvotes: 1